From 796da03f9f54f8fb193529288592571b371bf0cd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 5 Oct 2009 00:28:11 +0100 Subject: Something that compiles and runs, but otherwise utterly useless. Added a protocols/purple/ module and included it in the build system. Already picks up all the supported protocols and adds them individually. --- protocols/nogaim.c | 5 + protocols/purple/Makefile | 41 ++++++++ protocols/purple/purple.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 protocols/purple/Makefile create mode 100644 protocols/purple/purple.c (limited to 'protocols') diff --git a/protocols/nogaim.c b/protocols/nogaim.c index fd445324..8eae178d 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -117,6 +117,7 @@ void nogaim_init() extern void oscar_initmodule(); extern void byahoo_initmodule(); extern void jabber_initmodule(); + extern void purple_initmodule(); #ifdef WITH_MSN msn_initmodule(); @@ -133,6 +134,10 @@ void nogaim_init() #ifdef WITH_JABBER jabber_initmodule(); #endif + +#ifdef WITH_PURPLE + purple_initmodule(); +#endif #ifdef WITH_PLUGINS load_plugins(); diff --git a/protocols/purple/Makefile b/protocols/purple/Makefile new file mode 100644 index 00000000..bdefbd5f --- /dev/null +++ b/protocols/purple/Makefile @@ -0,0 +1,41 @@ +########################### +## Makefile for BitlBee ## +## ## +## Copyright 2002 Lintux ## +########################### + +### DEFINITIONS + +-include ../../Makefile.settings + +# [SH] Program variables +objects = purple.o + +CFLAGS += -Wall $$(pkg-config purple --cflags) +LFLAGS += -r + +# [SH] Phony targets +all: purple_mod.o +check: all +lcov: check +gcov: + gcov *.c + +.PHONY: all clean distclean + +clean: + rm -f *.o core + +distclean: clean + +### MAIN PROGRAM + +$(objects): ../../Makefile.settings Makefile + +$(objects): %.o: %.c + @echo '*' Compiling $< + @$(CC) -c $(CFLAGS) $< -o $@ + +purple_mod.o: $(objects) + @echo '*' Linking purple_mod.o + $(LD) $(LFLAGS) $(objects) -o purple_mod.o diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c new file mode 100644 index 00000000..333f6674 --- /dev/null +++ b/protocols/purple/purple.c @@ -0,0 +1,245 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* libpurple module - Main file * +* * +* Copyright 2009 Wilmer van der Gaast * +* * +* 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 along * +* with this program; if not, write to the Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +\***************************************************************************/ + +#include +#include + +#include "bitlbee.h" + +GSList *purple_connections; + +#undef g_io_add_watch +#undef g_io_add_watch_full +#undef g_timeout_add +#undef g_source_remove + +/** + * The following eventloop functions are used in both pidgin and purple-text. If your + * application uses glib mainloop, you can safely use this verbatim. + */ +#define PURPLE_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) +#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) + +typedef struct _PurpleGLibIOClosure { + PurpleInputFunction function; + guint result; + gpointer data; +} PurpleGLibIOClosure; + +static void purple_glib_io_destroy(gpointer data) +{ + g_free(data); +} + +static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) +{ + PurpleGLibIOClosure *closure = data; + PurpleInputCondition purple_cond = 0; + + if (condition & PURPLE_GLIB_READ_COND) + purple_cond |= PURPLE_INPUT_READ; + if (condition & PURPLE_GLIB_WRITE_COND) + purple_cond |= PURPLE_INPUT_WRITE; + + closure->function(closure->data, g_io_channel_unix_get_fd(source), + purple_cond); + + return TRUE; +} + +static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function, + gpointer data) +{ + PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1); + GIOChannel *channel; + GIOCondition cond = 0; + + closure->function = function; + closure->data = data; + + if (condition & PURPLE_INPUT_READ) + cond |= PURPLE_GLIB_READ_COND; + if (condition & PURPLE_INPUT_WRITE) + cond |= PURPLE_GLIB_WRITE_COND; + + channel = g_io_channel_unix_new(fd); + closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, + purple_glib_io_invoke, closure, purple_glib_io_destroy); + + g_io_channel_unref(channel); + return closure->result; +} + +static PurpleEventLoopUiOps glib_eventloops = +{ + g_timeout_add, + g_source_remove, + glib_input_add, + g_source_remove, + NULL, +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else + NULL, +#endif + + /* padding */ + NULL, + NULL, + NULL +}; + +static PurpleCoreUiOps bee_core_uiops = +{ + NULL, + NULL, + NULL, //null_ui_init, + NULL, + + /* padding */ + NULL, + NULL, + NULL, + NULL +}; + +static PurpleConversationUiOps bee_conv_uiops = +{ + NULL, /* create_conversation */ + NULL, /* destroy_conversation */ + NULL, /* write_chat */ + NULL, /* write_im */ + NULL, //null_write_conv, /* write_conv */ + NULL, /* chat_add_users */ + NULL, /* chat_rename_user */ + NULL, /* chat_remove_users */ + NULL, /* chat_update_user */ + NULL, /* present */ + NULL, /* has_focus */ + NULL, /* custom_smiley_add */ + NULL, /* custom_smiley_write */ + NULL, /* custom_smiley_close */ + NULL, /* send_confirm */ + NULL, + NULL, + NULL, + NULL +}; + +static void purple_init( account_t *acc ) +{ + set_t *s; + char str[16]; + +} + +static void purple_login( account_t *acc ) +{ + struct im_connection *ic = imcb_new( acc ); + struct ns_srv_reply *srv = NULL; + char *connect_to, *s; + int i; + + /* For now this is needed in the _connected() handlers if using + GLib event handling, to make sure we're not handling events + on dead connections. */ + purple_connections = g_slist_prepend( purple_connections, ic ); + +} + +static void purple_logout( struct im_connection *ic ) +{ + purple_connections = g_slist_remove( purple_connections, ic ); +} + +static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) +{ +} + +static GList *purple_away_states( struct im_connection *ic ) +{ +} + +static void purple_set_away( struct im_connection *ic, char *state_txt, char *message ) +{ +} + +static void purple_add_buddy( struct im_connection *ic, char *who, char *group ) +{ +} + +static void purple_remove_buddy( struct im_connection *ic, char *who, char *group ) +{ +} + +static void purple_keepalive( struct im_connection *ic ) +{ +} + +static int purple_send_typing( struct im_connection *ic, char *who, int typing ) +{ +} + +void purple_initmodule() +{ + GList *prots; + + purple_util_set_user_dir("/tmp"); + purple_debug_set_enabled(FALSE); + purple_core_set_ui_ops(&bee_core_uiops); + purple_eventloop_set_ui_ops(&glib_eventloops); + if( !purple_core_init( "BitlBee") ) + { + /* Initializing the core failed. Terminate. */ + fprintf( stderr, "libpurple initialization failed.\n" ); + abort(); + } + + /* This seems like stateful shit we don't want... */ + purple_set_blist(purple_blist_new()); + purple_blist_load(); + + /* Meh? */ + purple_prefs_load(); + + for( prots = purple_plugins_get_protocols(); prots; prots = prots->next ) + { + struct prpl *ret = g_new0( struct prpl, 1 ); + PurplePlugin *prot = prots->data; + + ret->name = prot->info->id; + ret->login = purple_login; + ret->init = purple_init; + ret->logout = purple_logout; + ret->buddy_msg = purple_buddy_msg; + ret->away_states = purple_away_states; + ret->set_away = purple_set_away; + ret->add_buddy = purple_add_buddy; + ret->remove_buddy = purple_remove_buddy; + ret->keepalive = purple_keepalive; + ret->send_typing = purple_send_typing; + ret->handle_cmp = g_strcasecmp; + + register_protocol( ret ); + } +} -- cgit v1.2.3 From 860ba6aaeabb25cd27ec70fb4a37d910dd5b3746 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 6 Oct 2009 00:32:34 +0100 Subject: Moved some stuff around, got something that logs in and reports status now. --- protocols/purple/purple.c | 152 +++++++++++++++++++++++++++++++++------------- 1 file changed, 109 insertions(+), 43 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 333f6674..5817373b 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -46,6 +46,18 @@ typedef struct _PurpleGLibIOClosure { gpointer data; } PurpleGLibIOClosure; +static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) +{ + PurpleAccount *pa = purple_connection_get_account( gc ); + GSList *i; + + for( i = purple_connections; i; i = i->next ) + if( ((struct im_connection *)i->data)->proto_data == pa ) + return i->data; + + return NULL; +} + static void purple_glib_io_destroy(gpointer data) { g_free(data); @@ -109,62 +121,31 @@ static PurpleEventLoopUiOps glib_eventloops = NULL }; -static PurpleCoreUiOps bee_core_uiops = -{ - NULL, - NULL, - NULL, //null_ui_init, - NULL, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static PurpleConversationUiOps bee_conv_uiops = -{ - NULL, /* create_conversation */ - NULL, /* destroy_conversation */ - NULL, /* write_chat */ - NULL, /* write_im */ - NULL, //null_write_conv, /* write_conv */ - NULL, /* chat_add_users */ - NULL, /* chat_rename_user */ - NULL, /* chat_remove_users */ - NULL, /* chat_update_user */ - NULL, /* present */ - NULL, /* has_focus */ - NULL, /* custom_smiley_add */ - NULL, /* custom_smiley_write */ - NULL, /* custom_smiley_close */ - NULL, /* send_confirm */ - NULL, - NULL, - NULL, - NULL -}; - static void purple_init( account_t *acc ) { - set_t *s; - char str[16]; - + /* TODO: Figure out variables to export via set. */ } static void purple_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); - struct ns_srv_reply *srv = NULL; - char *connect_to, *s; - int i; + PurpleAccount *pa; + PurpleSavedStatus *ps; /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events on dead connections. */ purple_connections = g_slist_prepend( purple_connections, ic ); + pa = purple_account_new( acc->user, acc->prpl->name ); + purple_account_set_password( pa, acc->pass ); + + ic->proto_data = pa; + + purple_account_set_enabled( pa, "BitlBee", TRUE ); + + //ps = purple_savedstatus_new( NULL, PURPLE_STATUS_AVAILABLE ); + //purple_savedstatus_activate_for_account( ps, pa ); } static void purple_logout( struct im_connection *ic ) @@ -178,6 +159,7 @@ static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, static GList *purple_away_states( struct im_connection *ic ) { + return NULL; } static void purple_set_away( struct im_connection *ic, char *state_txt, char *message ) @@ -200,6 +182,90 @@ static int purple_send_typing( struct im_connection *ic, char *who, int typing ) { } +static void purple_ui_init(); + +static PurpleCoreUiOps bee_core_uiops = +{ + NULL, + NULL, + purple_ui_init, + NULL, + + /* padding */ + NULL, + NULL, + NULL, + NULL +}; + +static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count ) +{ + imcb_log( purple_ic_by_gc( gc ), "%s", text ); +} + +static void prplcb_conn_connected( PurpleConnection *gc ) +{ + imcb_connected( purple_ic_by_gc( gc ) ); +} + +static void prplcb_conn_disconnected( PurpleConnection *gc ) +{ + imc_logout( purple_ic_by_gc( gc ), TRUE ); +} + +static void prplcb_conn_notice( PurpleConnection *gc, const char *text ) +{ + imcb_log( purple_ic_by_gc( gc ), "%s", text ); +} + +static void prplcb_conn_report_disconnect_reason( PurpleConnection *gc, PurpleConnectionError reason, const char *text ) +{ + /* PURPLE_CONNECTION_ERROR_NAME_IN_USE means concurrent login, + should probably handle that. */ + imcb_error( purple_ic_by_gc( gc ), "%s", text ); +} + +static PurpleConnectionUiOps bee_conn_uiops = +{ + prplcb_conn_progress, + prplcb_conn_connected, + prplcb_conn_disconnected, + prplcb_conn_notice, + NULL, + NULL, + NULL, + prplcb_conn_report_disconnect_reason, +}; + +static PurpleConversationUiOps bee_conv_uiops = +{ + NULL, /* create_conversation */ + NULL, /* destroy_conversation */ + NULL, /* write_chat */ + NULL, /* write_im */ + NULL, //null_write_conv, /* write_conv */ + NULL, /* chat_add_users */ + NULL, /* chat_rename_user */ + NULL, /* chat_remove_users */ + NULL, /* chat_update_user */ + NULL, /* present */ + NULL, /* has_focus */ + NULL, /* custom_smiley_add */ + NULL, /* custom_smiley_write */ + NULL, /* custom_smiley_close */ + NULL, /* send_confirm */ + NULL, + NULL, + NULL, + NULL +}; + +static void purple_ui_init() +{ + purple_connections_set_ui_ops( &bee_conn_uiops ); + purple_conversations_set_ui_ops( &bee_conv_uiops ); +} + void purple_initmodule() { GList *prots; -- cgit v1.2.3 From 7da726b12a546a5022d8f91fa3a34764335ba037 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 6 Oct 2009 22:49:42 +0100 Subject: Getting a contact list and online status now. Time to handle messages. --- protocols/purple/purple.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 5817373b..5807d01a 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -46,9 +46,8 @@ typedef struct _PurpleGLibIOClosure { gpointer data; } PurpleGLibIOClosure; -static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) +static struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) { - PurpleAccount *pa = purple_connection_get_account( gc ); GSList *i; for( i = purple_connections; i; i = i->next ) @@ -58,6 +57,11 @@ static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) return NULL; } +static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) +{ + return purple_ic_by_pa( purple_connection_get_account( gc ) ); +} + static void purple_glib_io_destroy(gpointer data) { g_free(data); @@ -237,6 +241,48 @@ static PurpleConnectionUiOps bee_conn_uiops = prplcb_conn_report_disconnect_reason, }; +static void prplcb_blist_new( PurpleBlistNode *node ) +{ + PurpleBuddy *bud = (PurpleBuddy*) node; + struct im_connection *ic = purple_ic_by_pa( bud->account ); + + if( node->type == PURPLE_BLIST_BUDDY_NODE ) + { + imcb_add_buddy( ic, bud->name, NULL ); + if( bud->server_alias ) + imcb_buddy_nick_hint( ic, bud->name, bud->server_alias ); + } +} + +static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) +{ + PurpleBuddy *bud = (PurpleBuddy*) node; + + if( node->type == PURPLE_BLIST_BUDDY_NODE ) + { + imcb_buddy_status( purple_ic_by_pa( bud->account ), bud->name, + purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0, + NULL, NULL ); + } +} + +static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) +{ + PurpleBuddy *bud = (PurpleBuddy*) node; + + if( node->type == PURPLE_BLIST_BUDDY_NODE ) + imcb_remove_buddy( purple_ic_by_pa( bud->account ), bud->name, NULL ); +} + +static PurpleBlistUiOps bee_blist_uiops = +{ + NULL, + prplcb_blist_new, + NULL, + prplcb_blist_update, + prplcb_blist_remove, +}; + static PurpleConversationUiOps bee_conv_uiops = { NULL, /* create_conversation */ @@ -262,6 +308,7 @@ static PurpleConversationUiOps bee_conv_uiops = static void purple_ui_init() { + purple_blist_set_ui_ops( &bee_blist_uiops ); purple_connections_set_ui_ops( &bee_conn_uiops ); purple_conversations_set_ui_ops( &bee_conv_uiops ); } -- cgit v1.2.3 From d250b2a5fa95724613d0176ce85a6c6859407ce6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 6 Oct 2009 23:26:01 +0100 Subject: Receive messages. --- protocols/purple/purple.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 5807d01a..9edba87e 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -209,7 +209,12 @@ static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t static void prplcb_conn_connected( PurpleConnection *gc ) { - imcb_connected( purple_ic_by_gc( gc ) ); + struct im_connection *ic = purple_ic_by_gc( gc ); + + imcb_connected( ic ); + + if( gc->flags & PURPLE_CONNECTION_HTML ) + ic->flags |= OPT_DOES_HTML; } static void prplcb_conn_disconnected( PurpleConnection *gc ) @@ -283,12 +288,19 @@ static PurpleBlistUiOps bee_blist_uiops = prplcb_blist_remove, }; +static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) +{ + struct im_connection *ic = purple_ic_by_pa( conv->account ); + + imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); +} + static PurpleConversationUiOps bee_conv_uiops = { NULL, /* create_conversation */ NULL, /* destroy_conversation */ NULL, /* write_chat */ - NULL, /* write_im */ + prplcb_conv_im, /* write_im */ NULL, //null_write_conv, /* write_conv */ NULL, /* chat_add_users */ NULL, /* chat_rename_user */ -- cgit v1.2.3 From 389f7bed787168abcc8aa5d01cdd49946cb863b6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 6 Oct 2009 23:55:46 +0100 Subject: Support for sending messages. --- protocols/purple/purple.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 9edba87e..3c86490d 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -159,6 +159,16 @@ static void purple_logout( struct im_connection *ic ) static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) { + PurpleConversation *conv; + + if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM, + who, ic->proto_data ) ) == NULL ) + { + conv = purple_conversation_new( PURPLE_CONV_TYPE_IM, + ic->proto_data, who ); + } + + purple_conv_im_send( purple_conversation_get_im_data( conv ), message ); } static GList *purple_away_states( struct im_connection *ic ) @@ -292,7 +302,9 @@ static void prplcb_conv_im( PurpleConversation *conv, const char *who, const cha { struct im_connection *ic = purple_ic_by_pa( conv->account ); - imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); + /* ..._SEND means it's an outgoing message, no need to echo those. */ + if( !( flags & PURPLE_MESSAGE_SEND ) ) + imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); } static PurpleConversationUiOps bee_conv_uiops = -- cgit v1.2.3 From 0cbef26bd1f82787a8107e92b14839a59187e0c2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 8 Oct 2009 00:37:32 +0100 Subject: Added some debugging stuff and handling (better said, ignoring) of events for closed connections where necessary. --- protocols/purple/purple.c | 60 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 10 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 3c86490d..cd908832 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -128,13 +128,15 @@ static PurpleEventLoopUiOps glib_eventloops = static void purple_init( account_t *acc ) { /* TODO: Figure out variables to export via set. */ + } static void purple_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); PurpleAccount *pa; - PurpleSavedStatus *ps; + //PurpleSavedStatus *ps; + GList *i; /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events @@ -148,6 +150,15 @@ static void purple_login( account_t *acc ) purple_account_set_enabled( pa, "BitlBee", TRUE ); + /* + for( i = ((PurplePluginProtocolInfo *)pa->gc->prpl->info->extra_info)->protocol_options; i; i = i->next ) + { + PurpleAccountOption *o = i->data; + + printf( "%s\n", o->pref_name ); + } + */ + //ps = purple_savedstatus_new( NULL, PURPLE_STATUS_AVAILABLE ); //purple_savedstatus_activate_for_account( ps, pa ); } @@ -169,6 +180,8 @@ static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, } purple_conv_im_send( purple_conversation_get_im_data( conv ), message ); + + return 1; } static GList *purple_away_states( struct im_connection *ic ) @@ -194,6 +207,7 @@ static void purple_keepalive( struct im_connection *ic ) static int purple_send_typing( struct im_connection *ic, char *who, int typing ) { + return 1; } static void purple_ui_init(); @@ -214,7 +228,9 @@ static PurpleCoreUiOps bee_core_uiops = static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count ) { - imcb_log( purple_ic_by_gc( gc ), "%s", text ); + struct im_connection *ic = purple_ic_by_gc( gc ); + + imcb_log( ic, "%s", text ); } static void prplcb_conn_connected( PurpleConnection *gc ) @@ -229,19 +245,28 @@ static void prplcb_conn_connected( PurpleConnection *gc ) static void prplcb_conn_disconnected( PurpleConnection *gc ) { - imc_logout( purple_ic_by_gc( gc ), TRUE ); + struct im_connection *ic = purple_ic_by_gc( gc ); + + if( ic != NULL ) + imc_logout( ic, TRUE ); } static void prplcb_conn_notice( PurpleConnection *gc, const char *text ) { - imcb_log( purple_ic_by_gc( gc ), "%s", text ); + struct im_connection *ic = purple_ic_by_gc( gc ); + + if( ic != NULL ) + imcb_log( ic, "%s", text ); } static void prplcb_conn_report_disconnect_reason( PurpleConnection *gc, PurpleConnectionError reason, const char *text ) { + struct im_connection *ic = purple_ic_by_gc( gc ); + /* PURPLE_CONNECTION_ERROR_NAME_IN_USE means concurrent login, should probably handle that. */ - imcb_error( purple_ic_by_gc( gc ), "%s", text ); + if( ic != NULL ) + imcb_error( ic, "%s", text ); } static PurpleConnectionUiOps bee_conn_uiops = @@ -261,7 +286,7 @@ static void prplcb_blist_new( PurpleBlistNode *node ) PurpleBuddy *bud = (PurpleBuddy*) node; struct im_connection *ic = purple_ic_by_pa( bud->account ); - if( node->type == PURPLE_BLIST_BUDDY_NODE ) + if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL ) { imcb_add_buddy( ic, bud->name, NULL ); if( bud->server_alias ) @@ -272,10 +297,11 @@ static void prplcb_blist_new( PurpleBlistNode *node ) static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) { PurpleBuddy *bud = (PurpleBuddy*) node; + struct im_connection *ic = purple_ic_by_pa( bud->account ); - if( node->type == PURPLE_BLIST_BUDDY_NODE ) + if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL ) { - imcb_buddy_status( purple_ic_by_pa( bud->account ), bud->name, + imcb_buddy_status( ic, bud->name, purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0, NULL, NULL ); } @@ -284,9 +310,12 @@ static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) { PurpleBuddy *bud = (PurpleBuddy*) node; + struct im_connection *ic = purple_ic_by_pa( bud->account ); - if( node->type == PURPLE_BLIST_BUDDY_NODE ) - imcb_remove_buddy( purple_ic_by_pa( bud->account ), bud->name, NULL ); + if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL ) + { + imcb_remove_buddy( ic, bud->name, NULL ); + } } static PurpleBlistUiOps bee_blist_uiops = @@ -330,11 +359,22 @@ static PurpleConversationUiOps bee_conv_uiops = NULL }; +static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s ) +{ + printf( "DEBUG %s: %s", category, arg_s ); +} + +static PurpleDebugUiOps bee_debug_uiops = +{ + prplcb_debug_print, +}; + static void purple_ui_init() { purple_blist_set_ui_ops( &bee_blist_uiops ); purple_connections_set_ui_ops( &bee_conn_uiops ); purple_conversations_set_ui_ops( &bee_conv_uiops ); + //purple_debug_set_ui_ops( &bee_debug_uiops ); } void purple_initmodule() -- cgit v1.2.3 From e046390da36e369c94af607fdedfe7b9f99d9e47 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Oct 2009 00:25:54 +0100 Subject: Make purple use BitlBee's event handling API. Since the APIs never really diverged too much this is fairly transparent. I did rename and redefine GAIM_INPUT_* variables to really make it work without adding another stupid layer in between. One problem left, the new libpurple input API doesn't care about return values. Fixing that in the next CL. --- protocols/jabber/io.c | 4 +-- protocols/msn/ns.c | 2 +- protocols/msn/sb.c | 2 +- protocols/oscar/oscar.c | 14 ++++----- protocols/purple/purple.c | 72 +++++++++++------------------------------------ protocols/yahoo/yahoo.c | 4 +-- 6 files changed, 30 insertions(+), 68 deletions(-) (limited to 'protocols') diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 10efad37..3b0ef3ef 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -63,7 +63,7 @@ int jabber_write( struct im_connection *ic, char *buf, int len ) it via the event handler. If not, add the handler. (In most cases it probably won't be necessary.) */ if( ( ret = jabber_write_queue( ic ) ) && jd->tx_len > 0 ) - jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, ic ); + jd->w_inpa = b_input_add( jd->fd, B_EV_IO_WRITE, jabber_write_callback, ic ); } else { @@ -528,7 +528,7 @@ gboolean jabber_start_stream( struct im_connection *ic ) jd->xt = xt_new( jabber_handlers, ic ); if( jd->r_inpa <= 0 ) - jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic ); + jd->r_inpa = b_input_add( jd->fd, B_EV_IO_READ, jabber_read_callback, ic ); greet = g_strdup_printf( "" "trId ); if( msn_write( ic, s, strlen( s ) ) ) { - ic->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, ic ); + ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); imcb_log( ic, "Connected to server, waiting for reply" ); } diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index e9526234..b0f7a2c5 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -308,7 +308,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session ); if( msn_sb_write( sb, buf, strlen( buf ) ) ) - sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb ); + sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb ); else debug( "Error %d while connecting to switchboard server", 2 ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 1118c26d..06b8100f 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -290,7 +290,7 @@ static gboolean oscar_callback(gpointer data, gint source, odata = (struct oscar_data *)ic->proto_data; - if (condition & GAIM_INPUT_READ) { + if (condition & B_EV_IO_READ) { if (aim_get_command(odata->sess, conn) >= 0) { aim_rxdispatch(odata->sess); if (odata->killme) @@ -362,7 +362,7 @@ static gboolean oscar_login_connect(gpointer data, gint source, b_input_conditio } aim_conn_completeconnect(sess, conn); - ic->inpa = b_input_add(conn->fd, GAIM_INPUT_READ, + ic->inpa = b_input_add(conn->fd, B_EV_IO_READ, oscar_callback, conn); return FALSE; @@ -486,7 +486,7 @@ static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition } aim_conn_completeconnect(sess, bosconn); - ic->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ, + ic->inpa = b_input_add(bosconn->fd, B_EV_IO_READ, oscar_callback, bosconn); imcb_log(ic, _("Connection established, cookie sent")); @@ -662,7 +662,7 @@ static gboolean straight_to_hell(gpointer data, gint source, b_input_condition c write(pos->fd, buf, strlen(buf)); if (pos->modname) g_free(pos->modname); - pos->inpa = b_input_add(pos->fd, GAIM_INPUT_READ, damn_you, pos); + pos->inpa = b_input_add(pos->fd, B_EV_IO_READ, damn_you, pos); return FALSE; } @@ -831,7 +831,7 @@ static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condit } aim_conn_completeconnect(sess, tstconn); - odata->cnpa = b_input_add(tstconn->fd, GAIM_INPUT_READ, + odata->cnpa = b_input_add(tstconn->fd, B_EV_IO_READ, oscar_callback, tstconn); return FALSE; @@ -859,7 +859,7 @@ static gboolean oscar_auth_connect(gpointer data, gint source, b_input_condition } aim_conn_completeconnect(sess, tstconn); - odata->paspa = b_input_add(tstconn->fd, GAIM_INPUT_READ, + odata->paspa = b_input_add(tstconn->fd, B_EV_IO_READ, oscar_callback, tstconn); return FALSE; @@ -895,7 +895,7 @@ static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition aim_conn_completeconnect(sess, ccon->conn); ccon->inpa = b_input_add(tstconn->fd, - GAIM_INPUT_READ, + B_EV_IO_READ, oscar_callback, tstconn); odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon); diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index cd908832..08c14edf 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -62,67 +62,22 @@ static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) return purple_ic_by_pa( purple_connection_get_account( gc ) ); } -static void purple_glib_io_destroy(gpointer data) +static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata ) { - g_free(data); + return b_timeout_add( interval, (b_event_handler) func, udata ); } -static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) +static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata ) { - PurpleGLibIOClosure *closure = data; - PurpleInputCondition purple_cond = 0; - - if (condition & PURPLE_GLIB_READ_COND) - purple_cond |= PURPLE_INPUT_READ; - if (condition & PURPLE_GLIB_WRITE_COND) - purple_cond |= PURPLE_INPUT_WRITE; - - closure->function(closure->data, g_io_channel_unix_get_fd(source), - purple_cond); - - return TRUE; -} - -static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function, - gpointer data) -{ - PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1); - GIOChannel *channel; - GIOCondition cond = 0; - - closure->function = function; - closure->data = data; - - if (condition & PURPLE_INPUT_READ) - cond |= PURPLE_GLIB_READ_COND; - if (condition & PURPLE_INPUT_WRITE) - cond |= PURPLE_GLIB_WRITE_COND; - - channel = g_io_channel_unix_new(fd); - closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, - purple_glib_io_invoke, closure, purple_glib_io_destroy); - - g_io_channel_unref(channel); - return closure->result; + return (guint) b_input_add( fd, cond, (b_event_handler) func, udata ); } static PurpleEventLoopUiOps glib_eventloops = { - g_timeout_add, - g_source_remove, - glib_input_add, - g_source_remove, - NULL, -#if GLIB_CHECK_VERSION(2,14,0) - g_timeout_add_seconds, -#else - NULL, -#endif - - /* padding */ - NULL, - NULL, - NULL + prplcb_ev_timeout_add, + b_event_remove, + prplcb_ev_input_add, + b_event_remove, }; static void purple_init( account_t *acc ) @@ -136,7 +91,7 @@ static void purple_login( account_t *acc ) struct im_connection *ic = imcb_new( acc ); PurpleAccount *pa; //PurpleSavedStatus *ps; - GList *i; + //GList *i; /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events @@ -342,7 +297,7 @@ static PurpleConversationUiOps bee_conv_uiops = NULL, /* destroy_conversation */ NULL, /* write_chat */ prplcb_conv_im, /* write_im */ - NULL, //null_write_conv, /* write_conv */ + NULL, /* write_conv */ NULL, /* chat_add_users */ NULL, /* chat_rename_user */ NULL, /* chat_remove_users */ @@ -381,6 +336,13 @@ void purple_initmodule() { GList *prots; + if( B_EV_IO_READ != PURPLE_INPUT_READ || + B_EV_IO_WRITE != PURPLE_INPUT_WRITE ) + { + /* FIXME FIXME FIXME FIXME FIXME :-) */ + exit( 1 ); + } + purple_util_set_user_dir("/tmp"); purple_debug_set_enabled(FALSE); purple_core_set_ui_ops(&bee_core_uiops); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 3e844c55..65993d9d 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -681,7 +681,7 @@ int ext_yahoo_add_handler( int id, int fd, yahoo_input_condition cond, void *dat d->data = data; inp->d = d; - d->tag = inp->h = b_input_add( fd, GAIM_INPUT_READ, (b_event_handler) byahoo_read_ready_callback, (gpointer) d ); + d->tag = inp->h = b_input_add( fd, B_EV_IO_READ, (b_event_handler) byahoo_read_ready_callback, (gpointer) d ); } else if( cond == YAHOO_INPUT_WRITE ) { @@ -692,7 +692,7 @@ int ext_yahoo_add_handler( int id, int fd, yahoo_input_condition cond, void *dat d->data = data; inp->d = d; - d->tag = inp->h = b_input_add( fd, GAIM_INPUT_WRITE, (b_event_handler) byahoo_write_ready_callback, (gpointer) d ); + d->tag = inp->h = b_input_add( fd, B_EV_IO_WRITE, (b_event_handler) byahoo_write_ready_callback, (gpointer) d ); } else { -- cgit v1.2.3 From c5c18c155cfdc3edcbd764633761d33e3c5992a3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Oct 2009 00:57:26 +0100 Subject: Hacked up a B_EV_FLAG_FORCE_REPEAT event handler flag to make libpurple happy. --- protocols/purple/purple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 08c14edf..9ef70bd3 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -69,7 +69,7 @@ static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer u static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata ) { - return (guint) b_input_add( fd, cond, (b_event_handler) func, udata ); + return (guint) b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata ); } static PurpleEventLoopUiOps glib_eventloops = -- cgit v1.2.3 From 4164e620b4f593a427a89d9292f4aef5c33e9def Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Oct 2009 11:40:40 +0100 Subject: Fixing a few compiler warnings and cleaning up the last remains of GLib-specific code. --- protocols/purple/purple.c | 60 +++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 9ef70bd3..0a70b194 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -28,24 +28,6 @@ GSList *purple_connections; -#undef g_io_add_watch -#undef g_io_add_watch_full -#undef g_timeout_add -#undef g_source_remove - -/** - * The following eventloop functions are used in both pidgin and purple-text. If your - * application uses glib mainloop, you can safely use this verbatim. - */ -#define PURPLE_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) -#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) - -typedef struct _PurpleGLibIOClosure { - PurpleInputFunction function; - guint result; - gpointer data; -} PurpleGLibIOClosure; - static struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) { GSList *i; @@ -62,24 +44,6 @@ static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) return purple_ic_by_pa( purple_connection_get_account( gc ) ); } -static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata ) -{ - return b_timeout_add( interval, (b_event_handler) func, udata ); -} - -static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata ) -{ - return (guint) b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata ); -} - -static PurpleEventLoopUiOps glib_eventloops = -{ - prplcb_ev_timeout_add, - b_event_remove, - prplcb_ev_input_add, - b_event_remove, -}; - static void purple_init( account_t *acc ) { /* TODO: Figure out variables to export via set. */ @@ -324,6 +288,30 @@ static PurpleDebugUiOps bee_debug_uiops = prplcb_debug_print, }; +static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata ) +{ + return b_timeout_add( interval, (b_event_handler) func, udata ); +} + +static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata ) +{ + return b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata ); +} + +static gboolean prplcb_ev_remove( guint id ) +{ + b_event_remove( (gint) id ); + return TRUE; +} + +static PurpleEventLoopUiOps glib_eventloops = +{ + prplcb_ev_timeout_add, + prplcb_ev_remove, + prplcb_ev_input_add, + prplcb_ev_remove, +}; + static void purple_ui_init() { purple_blist_set_ui_ops( &bee_blist_uiops ); -- cgit v1.2.3 From 4f103ea401bb6b1ed8963ea33d4924f95e10473b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Oct 2009 12:26:09 +0100 Subject: Added handing of away states/messages of contacts. --- protocols/purple/purple.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 0a70b194..f1355e25 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -137,12 +137,6 @@ static PurpleCoreUiOps bee_core_uiops = NULL, purple_ui_init, NULL, - - /* padding */ - NULL, - NULL, - NULL, - NULL }; static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count ) @@ -220,9 +214,16 @@ static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL ) { - imcb_buddy_status( ic, bud->name, - purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0, - NULL, NULL ); + PurpleStatus *as; + int flags = 0; + + flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0; + flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY; + + as = purple_presence_get_active_status( bud->presence ); + + imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ), + purple_status_get_attr_string( as, "message" ) ); } } -- cgit v1.2.3 From db4cd40374ade33ccb1feae113f12a1dd0b6bf37 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Oct 2009 13:22:23 +0100 Subject: Some valgrind cleaning/type safety fixes. --- protocols/purple/purple.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index f1355e25..c9de15cd 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -84,7 +84,11 @@ static void purple_login( account_t *acc ) static void purple_logout( struct im_connection *ic ) { + PurpleAccount *pa = ic->proto_data; + + purple_account_set_enabled( pa, "BitlBee", FALSE ); purple_connections = g_slist_remove( purple_connections, ic ); + purple_account_destroy( pa ); } static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) @@ -197,10 +201,14 @@ static PurpleConnectionUiOps bee_conn_uiops = static void prplcb_blist_new( PurpleBlistNode *node ) { PurpleBuddy *bud = (PurpleBuddy*) node; - struct im_connection *ic = purple_ic_by_pa( bud->account ); - if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL ) + if( node->type == PURPLE_BLIST_BUDDY_NODE ) { + struct im_connection *ic = purple_ic_by_pa( bud->account ); + + if( ic == NULL ) + return; + imcb_add_buddy( ic, bud->name, NULL ); if( bud->server_alias ) imcb_buddy_nick_hint( ic, bud->name, bud->server_alias ); @@ -210,13 +218,16 @@ static void prplcb_blist_new( PurpleBlistNode *node ) static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) { PurpleBuddy *bud = (PurpleBuddy*) node; - struct im_connection *ic = purple_ic_by_pa( bud->account ); - if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL ) + if( node->type == PURPLE_BLIST_BUDDY_NODE ) { + struct im_connection *ic = purple_ic_by_pa( bud->account ); PurpleStatus *as; int flags = 0; + if( ic == NULL ) + return; + flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0; flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY; @@ -230,10 +241,14 @@ static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) { PurpleBuddy *bud = (PurpleBuddy*) node; - struct im_connection *ic = purple_ic_by_pa( bud->account ); - if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL ) + if( node->type == PURPLE_BLIST_BUDDY_NODE ) { + struct im_connection *ic = purple_ic_by_pa( bud->account ); + + if( ic == NULL ) + return; + imcb_remove_buddy( ic, bud->name, NULL ); } } -- cgit v1.2.3 From 0f7ee7e53f6bcb2d1d262a94c278440413c0103a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Oct 2009 13:57:29 +0100 Subject: Copy all the string/bool/int account settings with their defaults to "account set". They can be changed, but changes don't yet have any effect. --- protocols/purple/purple.c | 58 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 15 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index c9de15cd..f3d8f0f4 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -46,16 +46,56 @@ static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) static void purple_init( account_t *acc ) { - /* TODO: Figure out variables to export via set. */ + PurplePlugin *prpl = purple_plugins_find_with_id( acc->prpl->name ); + PurplePluginProtocolInfo *pi = prpl->info->extra_info; + GList *i; + for( i = pi->protocol_options; i; i = i->next ) + { + PurpleAccountOption *o = i->data; + const char *name; + char *def = NULL; + set_eval eval = NULL; + set_t *s; + + name = purple_account_option_get_setting( o ); + + switch( purple_account_option_get_type( o ) ) + { + case PURPLE_PREF_STRING: + def = g_strdup( purple_account_option_get_default_string( o ) ); + break; + + case PURPLE_PREF_INT: + def = g_strdup_printf( "%d", purple_account_option_get_default_int( o ) ); + eval = set_eval_int; + break; + + case PURPLE_PREF_BOOLEAN: + if( purple_account_option_get_default_bool( o ) ) + def = g_strdup( "true" ); + else + def = g_strdup( "false" ); + eval = set_eval_bool; + break; + + default: + fprintf( stderr, "Setting with unknown type: %s (%d)\n", name, purple_account_option_get_type( o ) ); + } + + if( def != NULL ) + { + s = set_add( &acc->set, name, def, eval, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; + g_free( def ); + } + } } static void purple_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); PurpleAccount *pa; - //PurpleSavedStatus *ps; - //GList *i; /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events @@ -68,18 +108,6 @@ static void purple_login( account_t *acc ) ic->proto_data = pa; purple_account_set_enabled( pa, "BitlBee", TRUE ); - - /* - for( i = ((PurplePluginProtocolInfo *)pa->gc->prpl->info->extra_info)->protocol_options; i; i = i->next ) - { - PurpleAccountOption *o = i->data; - - printf( "%s\n", o->pref_name ); - } - */ - - //ps = purple_savedstatus_new( NULL, PURPLE_STATUS_AVAILABLE ); - //purple_savedstatus_activate_for_account( ps, pa ); } static void purple_logout( struct im_connection *ic ) -- cgit v1.2.3 From b74b287af7ee980b01b89e911e21ec8f163d24b3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Oct 2009 22:08:26 +0100 Subject: Fixed account cleanup (use remove, not destroy) and now using user's account settings. --- protocols/purple/purple.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index f3d8f0f4..82978dc4 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -92,6 +92,43 @@ static void purple_init( account_t *acc ) } } +static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) +{ + PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id ); + PurplePluginProtocolInfo *pi = prpl->info->extra_info; + GList *i; + + for( i = pi->protocol_options; i; i = i->next ) + { + PurpleAccountOption *o = i->data; + const char *name; + set_t *s; + + name = purple_account_option_get_setting( o ); + s = set_find( &acc->set, name ); + if( s->value == NULL ) + continue; + + switch( purple_account_option_get_type( o ) ) + { + case PURPLE_PREF_STRING: + purple_account_set_string( pa, name, set_getstr( &acc->set, name ) ); + break; + + case PURPLE_PREF_INT: + purple_account_set_int( pa, name, set_getint( &acc->set, name ) ); + break; + + case PURPLE_PREF_BOOLEAN: + purple_account_set_bool( pa, name, set_getbool( &acc->set, name ) ); + break; + + default: + break; + } + } +} + static void purple_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); @@ -102,10 +139,9 @@ static void purple_login( account_t *acc ) on dead connections. */ purple_connections = g_slist_prepend( purple_connections, ic ); - pa = purple_account_new( acc->user, acc->prpl->name ); + ic->proto_data = pa = purple_account_new( acc->user, acc->prpl->name ); purple_account_set_password( pa, acc->pass ); - - ic->proto_data = pa; + purple_sync_settings( acc, pa ); purple_account_set_enabled( pa, "BitlBee", TRUE ); } @@ -116,7 +152,7 @@ static void purple_logout( struct im_connection *ic ) purple_account_set_enabled( pa, "BitlBee", FALSE ); purple_connections = g_slist_remove( purple_connections, ic ); - purple_account_destroy( pa ); + purple_accounts_remove( pa ); } static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) @@ -193,7 +229,9 @@ static void prplcb_conn_disconnected( PurpleConnection *gc ) struct im_connection *ic = purple_ic_by_gc( gc ); if( ic != NULL ) + { imc_logout( ic, TRUE ); + } } static void prplcb_conn_notice( PurpleConnection *gc, const char *text ) -- cgit v1.2.3 From ec5e57d6f165a462ac686341f9075243f0a4586a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 12 Oct 2009 01:00:24 +0100 Subject: Support for setting away states. Somewhat hackish but this stuff is hopelessly complicated in libpurple anyway.. --- protocols/purple/purple.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 82978dc4..c78b15e7 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -173,11 +173,34 @@ static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, static GList *purple_away_states( struct im_connection *ic ) { - return NULL; + PurpleAccount *pa = ic->proto_data; + GList *st, *ret = NULL; + + for( st = purple_account_get_status_types( pa ); st; st = st->next ) + { + printf( "%s\n", purple_status_type_get_name( st->data ) ); + ret = g_list_append( ret, (void*) purple_status_type_get_name( st->data ) ); + } + + return ret; } static void purple_set_away( struct im_connection *ic, char *state_txt, char *message ) { + PurpleAccount *pa = ic->proto_data; + GList *status_types = purple_account_get_status_types( pa ), *st; + PurpleStatusType *pst = NULL; + + for( st = status_types; st; st = st->next ) + { + pst = st->data; + + if( g_strcasecmp( state_txt, purple_status_type_get_name( pst ) ) == 0 ) + break; + } + + purple_account_set_status( pa, st ? purple_status_type_get_id( pst ) : "away", + TRUE, "message", message, NULL ); } static void purple_add_buddy( struct im_connection *ic, char *who, char *group ) @@ -354,10 +377,6 @@ static PurpleConversationUiOps bee_conv_uiops = NULL, /* custom_smiley_write */ NULL, /* custom_smiley_close */ NULL, /* send_confirm */ - NULL, - NULL, - NULL, - NULL }; static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s ) -- cgit v1.2.3 From dd0d57b10a8c2d07001ca2d4228232962ed8b95d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 12 Oct 2009 23:19:41 +0100 Subject: Oops, forgot to drop a printf() of all away states for debugging. --- protocols/purple/purple.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index c78b15e7..0e4a2f01 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -177,10 +177,7 @@ static GList *purple_away_states( struct im_connection *ic ) GList *st, *ret = NULL; for( st = purple_account_get_status_types( pa ); st; st = st->next ) - { - printf( "%s\n", purple_status_type_get_name( st->data ) ); ret = g_list_append( ret, (void*) purple_status_type_get_name( st->data ) ); - } return ret; } -- cgit v1.2.3 From e248c7ff061e1582ed4c2919de6d615c1813e87a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 12 Oct 2009 23:23:49 +0100 Subject: Automatically try prpl-$proto if $proto doesn't exist, and disable native protocol modules if purple is enabled; they don't go together very well. --- protocols/nogaim.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 8eae178d..7e8782ac 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -101,12 +101,23 @@ void register_protocol (struct prpl *p) struct prpl *find_protocol(const char *name) { GList *gl; - for (gl = protocols; gl; gl = gl->next) + + for( gl = protocols; gl; gl = gl->next ) { struct prpl *proto = gl->data; - if(!g_strcasecmp(proto->name, name)) + + if( g_strcasecmp( proto->name, name ) == 0 ) return proto; + +#ifdef WITH_PURPLE + /* I know, hardcoding is evil, but that doesn't make it + impossible. :-) */ + if( g_strncasecmp( proto->name, "prpl-", 5 ) == 0 && + g_strcasecmp( proto->name + 5, name ) == 0 ) + return proto; +#endif } + return NULL; } -- cgit v1.2.3 From 4524f664357f9f15e7535fc6f251c5be98d162da Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 12 Oct 2009 23:37:28 +0100 Subject: Store real names in /whois. --- protocols/purple/purple.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 0e4a2f01..aff4f3fa 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -297,7 +297,10 @@ static void prplcb_blist_new( PurpleBlistNode *node ) imcb_add_buddy( ic, bud->name, NULL ); if( bud->server_alias ) + { + imcb_rename_buddy( ic, bud->name, bud->server_alias ); imcb_buddy_nick_hint( ic, bud->name, bud->server_alias ); + } } } @@ -314,6 +317,9 @@ static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) if( ic == NULL ) return; + if( bud->server_alias ) + imcb_rename_buddy( ic, bud->name, bud->server_alias ); + flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0; flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY; -- cgit v1.2.3 From 6967d012be48db989ce2723a6ecc2b10b537c8f7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 14 Oct 2009 22:36:09 +0100 Subject: I think daemon mode and libpurple won't go together very well for now since libpurple seems to keep track of a merged contact list. For now people shouldn't be trying this combination. --- protocols/purple/purple.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index aff4f3fa..ca2a49f1 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -132,8 +132,16 @@ static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) static void purple_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); + static void *irc_check = NULL; PurpleAccount *pa; + if( irc_check != NULL && irc_check != acc->irc ) + { + irc_usermsg( acc->irc, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! Please use inetd or ForkDaemon mode instead." ); + return; + } + irc_check = acc->irc; + /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events on dead connections. */ @@ -384,7 +392,7 @@ static PurpleConversationUiOps bee_conv_uiops = static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s ) { - printf( "DEBUG %s: %s", category, arg_s ); + fprintf( stderr, "DEBUG %s: %s", category, arg_s ); } static PurpleDebugUiOps bee_debug_uiops = -- cgit v1.2.3 From b3117f2524775ff7c61ead7c3bdb3799064ed97f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 23 Nov 2009 22:58:20 +0000 Subject: Adding/removing contacts now works. --- protocols/purple/purple.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index ca2a49f1..6f1e6ae9 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -21,11 +21,11 @@ * * \***************************************************************************/ +#include "bitlbee.h" + #include #include -#include "bitlbee.h" - GSList *purple_connections; static struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) @@ -81,9 +81,10 @@ static void purple_init( account_t *acc ) default: fprintf( stderr, "Setting with unknown type: %s (%d)\n", name, purple_account_option_get_type( o ) ); + name = NULL; } - if( def != NULL ) + if( name != NULL ) { s = set_add( &acc->set, name, def, eval, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; @@ -210,10 +211,23 @@ static void purple_set_away( struct im_connection *ic, char *state_txt, char *me static void purple_add_buddy( struct im_connection *ic, char *who, char *group ) { + PurpleBuddy *pb; + + pb = purple_buddy_new( (PurpleAccount*) ic->proto_data, who, NULL ); + purple_blist_add_buddy( pb, NULL, NULL, NULL ); + purple_account_add_buddy( (PurpleAccount*) ic->proto_data, pb ); } static void purple_remove_buddy( struct im_connection *ic, char *who, char *group ) { + PurpleBuddy *pb; + + pb = purple_find_buddy( (PurpleAccount*) ic->proto_data, who ); + if( pb != NULL ) + { + purple_account_remove_buddy( (PurpleAccount*) ic->proto_data, pb, NULL ); + purple_blist_remove_buddy( pb ); + } } static void purple_keepalive( struct im_connection *ic ) @@ -342,6 +356,7 @@ static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) { PurpleBuddy *bud = (PurpleBuddy*) node; + /* if( node->type == PURPLE_BLIST_BUDDY_NODE ) { struct im_connection *ic = purple_ic_by_pa( bud->account ); @@ -351,6 +366,7 @@ static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) imcb_remove_buddy( ic, bud->name, NULL ); } + */ } static PurpleBlistUiOps bee_blist_uiops = -- cgit v1.2.3 From cd741d8e2bb0b7d08cf36d90f5332a639f190281 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 23 Nov 2009 23:23:37 +0000 Subject: Fixed compatibility with non-libpurple version: oscar is now recognized as a protocol name, and removed prpl- hack from nogaim.c. --- protocols/nogaim.c | 8 -------- protocols/nogaim.h | 1 + protocols/purple/purple.c | 43 ++++++++++++++++++++++++++++--------------- 3 files changed, 29 insertions(+), 23 deletions(-) (limited to 'protocols') diff --git a/protocols/nogaim.c b/protocols/nogaim.c index c0d4a953..f80653ff 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -110,14 +110,6 @@ struct prpl *find_protocol(const char *name) if( g_strcasecmp( proto->name, name ) == 0 ) return proto; - -#ifdef WITH_PURPLE - /* I know, hardcoding is evil, but that doesn't make it - impossible. :-) */ - if( g_strncasecmp( proto->name, "prpl-", 5 ) == 0 && - g_strcasecmp( proto->name + 5, name ) == 0 ) - return proto; -#endif } return NULL; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index dc6154e2..ae329b91 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -132,6 +132,7 @@ struct prpl { /* You should set this to the name of your protocol. * - The user sees this name ie. when imcb_log() is used. */ const char *name; + void *data; /* Added this one to be able to add per-account settings, don't think * it should be used for anything else. You are supposed to use the diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 6f1e6ae9..a8733f5d 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -148,7 +148,7 @@ static void purple_login( account_t *acc ) on dead connections. */ purple_connections = g_slist_prepend( purple_connections, ic ); - ic->proto_data = pa = purple_account_new( acc->user, acc->prpl->name ); + ic->proto_data = pa = purple_account_new( acc->user, (char*) acc->prpl->data ); purple_account_set_password( pa, acc->pass ); purple_sync_settings( acc, pa ); @@ -450,6 +450,7 @@ static void purple_ui_init() void purple_initmodule() { + struct prpl funcs; GList *prots; if( B_EV_IO_READ != PURPLE_INPUT_READ || @@ -477,24 +478,36 @@ void purple_initmodule() /* Meh? */ purple_prefs_load(); + memset( &funcs, 0, sizeof( funcs ) ); + funcs.login = purple_login; + funcs.init = purple_init; + funcs.logout = purple_logout; + funcs.buddy_msg = purple_buddy_msg; + funcs.away_states = purple_away_states; + funcs.set_away = purple_set_away; + funcs.add_buddy = purple_add_buddy; + funcs.remove_buddy = purple_remove_buddy; + funcs.keepalive = purple_keepalive; + funcs.send_typing = purple_send_typing; + funcs.handle_cmp = g_strcasecmp; + for( prots = purple_plugins_get_protocols(); prots; prots = prots->next ) { - struct prpl *ret = g_new0( struct prpl, 1 ); PurplePlugin *prot = prots->data; + struct prpl *ret; - ret->name = prot->info->id; - ret->login = purple_login; - ret->init = purple_init; - ret->logout = purple_logout; - ret->buddy_msg = purple_buddy_msg; - ret->away_states = purple_away_states; - ret->set_away = purple_set_away; - ret->add_buddy = purple_add_buddy; - ret->remove_buddy = purple_remove_buddy; - ret->keepalive = purple_keepalive; - ret->send_typing = purple_send_typing; - ret->handle_cmp = g_strcasecmp; - + ret = g_memdup( &funcs, sizeof( funcs ) ); + ret->name = ret->data = prot->info->id; + if( strncmp( ret->name, "prpl-", 5 ) == 0 ) + ret->name += 5; register_protocol( ret ); + + if( g_strcasecmp( prot->info->id, "prpl-aim" ) == 0 ) + { + ret = g_memdup( &funcs, sizeof( funcs ) ); + ret->name = "oscar"; + ret->data = prot->info->id; + register_protocol( ret ); + } } } -- cgit v1.2.3 From 45a19e543cc567981df92b62f428e0f89f94cb74 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 23 Nov 2009 23:38:31 +0000 Subject: Oops, forgot to change one protocol name string pointer.. --- protocols/purple/purple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index a8733f5d..f7b859ff 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -46,7 +46,7 @@ static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) static void purple_init( account_t *acc ) { - PurplePlugin *prpl = purple_plugins_find_with_id( acc->prpl->name ); + PurplePlugin *prpl = purple_plugins_find_with_id( (char*) acc->prpl->data ); PurplePluginProtocolInfo *pi = prpl->info->extra_info; GList *i; -- cgit v1.2.3 From 0ac1a37573f966d7a03b85816c583bd6976c402f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 25 Nov 2009 00:19:45 +0000 Subject: Added enough code to handle one class of queries (action-based), enough to make the "Please accept this SSL certificate" question work. Need to extend the BitlBee API a bit to *really* support this well though (yes/no is not enough). --- protocols/purple/purple.c | 90 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 4 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index f7b859ff..33b19a67 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -23,11 +23,18 @@ #include "bitlbee.h" +#include + #include #include GSList *purple_connections; +/* This makes me VERY sad... :-( But some libpurple callbacks come in without + any context so this is the only way to get that. Don't want to support + libpurple in daemon mode anyway. */ +static irc_t *local_irc; + static struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) { GSList *i; @@ -133,15 +140,15 @@ static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) static void purple_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); - static void *irc_check = NULL; PurpleAccount *pa; - if( irc_check != NULL && irc_check != acc->irc ) + if( local_irc != NULL && local_irc != acc->irc ) { - irc_usermsg( acc->irc, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! Please use inetd or ForkDaemon mode instead." ); + irc_usermsg( acc->irc, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! " + "Please use inetd or ForkDaemon mode instead." ); return; } - irc_check = acc->irc; + local_irc = acc->irc; /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events @@ -406,6 +413,80 @@ static PurpleConversationUiOps bee_conv_uiops = NULL, /* send_confirm */ }; +struct prplcb_request_action_data +{ + void *user_data, *bee_data; + PurpleRequestActionCb yes, no; + int yes_i, no_i; +}; + +static void prplcb_request_action_yes( void *data ) +{ + struct prplcb_request_action_data *pqad = data; + + pqad->yes( pqad->user_data, pqad->yes_i ); + g_free( pqad ); +} + +static void prplcb_request_action_no( void *data ) +{ + struct prplcb_request_action_data *pqad = data; + + pqad->no( pqad->user_data, pqad->no_i ); + g_free( pqad ); +} + +static void *prplcb_request_action( const char *title, const char *primary, const char *secondary, + int default_action, PurpleAccount *account, const char *who, + PurpleConversation *conv, void *user_data, size_t action_count, + va_list actions ) +{ + struct prplcb_request_action_data *pqad; + int i; + char *q; + + pqad = g_new0( struct prplcb_request_action_data, 1 ); + + for( i = 0; i < action_count; i ++ ) + { + char *caption; + void *fn; + + caption = va_arg( actions, char* ); + fn = va_arg( actions, void* ); + + if( strcmp( caption, "Accept" ) == 0 ) + { + pqad->yes = fn; + pqad->yes_i = i; + } + else if( strcmp( caption, "Reject" ) == 0 ) + { + pqad->no = fn; + pqad->no_i = i; + } + } + + pqad->user_data = user_data; + + q = g_strdup_printf( "Request: %s\n\n%s\n\n%s", title, primary, secondary ); + pqad->bee_data = query_add( local_irc, purple_ic_by_pa( account ), q, + prplcb_request_action_yes, prplcb_request_action_no, pqad ); + + g_free( q ); +} + +static PurpleRequestUiOps bee_request_uiops = +{ + NULL, + NULL, + prplcb_request_action, + NULL, + NULL, + NULL, + NULL, +}; + static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s ) { fprintf( stderr, "DEBUG %s: %s", category, arg_s ); @@ -445,6 +526,7 @@ static void purple_ui_init() purple_blist_set_ui_ops( &bee_blist_uiops ); purple_connections_set_ui_ops( &bee_conn_uiops ); purple_conversations_set_ui_ops( &bee_conv_uiops ); + purple_request_set_ui_ops( &bee_request_uiops ); //purple_debug_set_ui_ops( &bee_debug_uiops ); } -- cgit v1.2.3 From e5d8d21fd20516be53f873d269b469be109eca91 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 25 Nov 2009 00:45:27 +0000 Subject: Added in-memory help info, which I wanted to implement for ages already. Sadly the way I'm using it now doesn't work yet since nogaim_init() is called before help_init(). I'll fix that later. (Have to do that anyway to at least make ForkDaemon mode work..) --- protocols/purple/purple.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 33b19a67..50770187 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -22,6 +22,7 @@ \***************************************************************************/ #include "bitlbee.h" +#include "help.h" #include @@ -474,6 +475,8 @@ static void *prplcb_request_action( const char *title, const char *primary, cons prplcb_request_action_yes, prplcb_request_action_no, pqad ); g_free( q ); + + return pqad; } static PurpleRequestUiOps bee_request_uiops = @@ -534,6 +537,7 @@ void purple_initmodule() { struct prpl funcs; GList *prots; + GString *help; if( B_EV_IO_READ != PURPLE_INPUT_READ || B_EV_IO_WRITE != PURPLE_INPUT_WRITE ) @@ -573,6 +577,8 @@ void purple_initmodule() funcs.send_typing = purple_send_typing; funcs.handle_cmp = g_strcasecmp; + help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); + for( prots = purple_plugins_get_protocols(); prots; prots = prots->next ) { PurplePlugin *prot = prots->data; @@ -584,6 +590,8 @@ void purple_initmodule() ret->name += 5; register_protocol( ret ); + g_string_append_printf( help, "\n* %s (%s)", ret->name, prot->info->name ); + if( g_strcasecmp( prot->info->id, "prpl-aim" ) == 0 ) { ret = g_memdup( &funcs, sizeof( funcs ) ); @@ -592,4 +600,7 @@ void purple_initmodule() register_protocol( ret ); } } + + help_add_mem( &global.help, "purple", help->str ); + g_string_free( help, TRUE ); } -- cgit v1.2.3 From 487f555c687571cee39d69b3954b4d1f82811d29 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 26 Nov 2009 00:04:40 +0000 Subject: Support for sending zomg-im-typing notifications. --- protocols/purple/purple.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 50770187..6bb8fc99 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -242,9 +242,26 @@ static void purple_keepalive( struct im_connection *ic ) { } -static int purple_send_typing( struct im_connection *ic, char *who, int typing ) +static int purple_send_typing( struct im_connection *ic, char *who, int flags ) { - return 1; + PurpleTypingState state = PURPLE_NOT_TYPING; + PurpleConversation *conv; + + if( flags & OPT_TYPING ) + state = PURPLE_TYPING; + else if( flags & OPT_THINKING ) + state = PURPLE_TYPED; + + if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM, + who, ic->proto_data ) ) == NULL ) + { + purple_conv_im_set_typing_state( purple_conversation_get_im_data( conv ), state ); + return 1; + } + else + { + return 0; + } } static void purple_ui_init(); -- cgit v1.2.3 From 3e7b640db6ae2d77122d93dcf5f1a0989ef0b3f1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 28 Nov 2009 00:47:20 +0000 Subject: Look up a buddy in the contact list on incoming msgs. This seems to be the best way to "normalize" handles (i.e. chopping off the resource part of JIDs). --- protocols/purple/purple.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 6bb8fc99..f28e5cf0 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -379,9 +379,9 @@ static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) { + /* PurpleBuddy *bud = (PurpleBuddy*) node; - /* if( node->type == PURPLE_BLIST_BUDDY_NODE ) { struct im_connection *ic = purple_ic_by_pa( bud->account ); @@ -406,10 +406,17 @@ static PurpleBlistUiOps bee_blist_uiops = static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) { struct im_connection *ic = purple_ic_by_pa( conv->account ); + PurpleBuddy *buddy; /* ..._SEND means it's an outgoing message, no need to echo those. */ - if( !( flags & PURPLE_MESSAGE_SEND ) ) - imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); + if( flags & PURPLE_MESSAGE_SEND ) + return; + + buddy = purple_find_buddy( conv->account, who ); + if( buddy != NULL ) + who = purple_buddy_get_contact_alias( buddy ); + + imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); } static PurpleConversationUiOps bee_conv_uiops = -- cgit v1.2.3 From a19ea7a21e082d0e28aea7198bea0f3bd3e2eb4f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 26 Dec 2009 16:14:52 +0100 Subject: Use purple_buddy_get_name, not purple_buddy_get_contact_alias. Makes sense, but I'm actually not sure if this function *is* the right one. Fixes issues with messages coming from the wrong handle. --- protocols/purple/purple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index f28e5cf0..ce7f0e56 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -414,7 +414,7 @@ static void prplcb_conv_im( PurpleConversation *conv, const char *who, const cha buddy = purple_find_buddy( conv->account, who ); if( buddy != NULL ) - who = purple_buddy_get_contact_alias( buddy ); + who = purple_buddy_get_name( buddy ); imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); } -- cgit v1.2.3 From e08e53c9398700309000c6e6b7ff895185d567a9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 4 Jan 2010 12:16:18 +0000 Subject: Fixed build system: Run pkg-config at configure-time instead of just failing mysteriously at build time if libpurple-dev is missing. --- protocols/purple/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/Makefile b/protocols/purple/Makefile index bdefbd5f..15460529 100644 --- a/protocols/purple/Makefile +++ b/protocols/purple/Makefile @@ -11,7 +11,7 @@ # [SH] Program variables objects = purple.o -CFLAGS += -Wall $$(pkg-config purple --cflags) +CFLAGS += -Wall $(PURPLE_CFLAGS) LFLAGS += -r # [SH] Phony targets -- cgit v1.2.3 From 279607e52513bba31b7dfdd508d51e9ac24950c2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 7 Mar 2010 22:35:00 +0000 Subject: Fixed purple module to work with the new away interface. --- protocols/purple/purple.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index ce7f0e56..0873b6f5 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -194,7 +194,11 @@ static GList *purple_away_states( struct im_connection *ic ) GList *st, *ret = NULL; for( st = purple_account_get_status_types( pa ); st; st = st->next ) - ret = g_list_append( ret, (void*) purple_status_type_get_name( st->data ) ); + { + PurpleStatusPrimitive prim = purple_status_type_get_primitive( st->data ); + if( prim != PURPLE_STATUS_AVAILABLE && prim != PURPLE_STATUS_OFFLINE ) + ret = g_list_append( ret, (void*) purple_status_type_get_name( st->data ) ); + } return ret; } @@ -204,17 +208,31 @@ static void purple_set_away( struct im_connection *ic, char *state_txt, char *me PurpleAccount *pa = ic->proto_data; GList *status_types = purple_account_get_status_types( pa ), *st; PurpleStatusType *pst = NULL; + GList *args = NULL; for( st = status_types; st; st = st->next ) { pst = st->data; - if( g_strcasecmp( state_txt, purple_status_type_get_name( pst ) ) == 0 ) + if( state_txt == NULL && + purple_status_type_get_primitive( st->data ) == PURPLE_STATUS_AVAILABLE ) + break; + + if( state_txt != NULL && + g_strcasecmp( state_txt, purple_status_type_get_name( pst ) ) == 0 ) break; } - purple_account_set_status( pa, st ? purple_status_type_get_id( pst ) : "away", - TRUE, "message", message, NULL ); + if( message ) + { + args = g_list_append( args, "message" ); + args = g_list_append( args, message ); + } + + purple_account_set_status_list( pa, st ? purple_status_type_get_id( pst ) : "away", + TRUE, args ); + + g_list_free( args ); } static void purple_add_buddy( struct im_connection *ic, char *who, char *group ) -- cgit v1.2.3 From 52cae01137057f2cc3def802a661fef92cedbcae Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 7 Mar 2010 23:08:40 +0000 Subject: Set the ACC_FLAG_*_MESSAGE flags correctly depending on the prpl. --- protocols/purple/purple.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 0873b6f5..6a9472dc 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * libpurple module - Main file * * * -* Copyright 2009 Wilmer van der Gaast * +* Copyright 2010 Wilmer van der Gaast * * * * 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 * @@ -56,8 +56,10 @@ static void purple_init( account_t *acc ) { PurplePlugin *prpl = purple_plugins_find_with_id( (char*) acc->prpl->data ); PurplePluginProtocolInfo *pi = prpl->info->extra_info; - GList *i; + PurpleAccount *pa; + GList *i, *st; + /* Convert all protocol_options into per-account setting variables. */ for( i = pi->protocol_options; i; i = i->next ) { PurpleAccountOption *o = i->data; @@ -99,6 +101,26 @@ static void purple_init( account_t *acc ) g_free( def ); } } + + /* Go through all away states to figure out if away/status messages + are possible. */ + pa = purple_account_new( acc->user, (char*) acc->prpl->data ); + for( st = purple_account_get_status_types( pa ); st; st = st->next ) + { + PurpleStatusPrimitive prim = purple_status_type_get_primitive( st->data ); + + if( prim == PURPLE_STATUS_AVAILABLE ) + { + if( purple_status_type_get_attr( st->data, "message" ) ) + acc->flags |= ACC_FLAG_STATUS_MESSAGE; + } + else if( prim != PURPLE_STATUS_OFFLINE ) + { + if( purple_status_type_get_attr( st->data, "message" ) ) + acc->flags |= ACC_FLAG_AWAY_MESSAGE; + } + } + purple_accounts_remove( pa ); } static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) @@ -223,7 +245,7 @@ static void purple_set_away( struct im_connection *ic, char *state_txt, char *me break; } - if( message ) + if( message && purple_status_type_get_attr( st, "message" ) ) { args = g_list_append( args, "message" ); args = g_list_append( args, message ); -- cgit v1.2.3 From bab1c86e9e07553f58ab4ebdaad7f74018052b5e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 8 Mar 2010 01:21:08 +0000 Subject: Mail notifications, partially from http://irc.nfx.cz/patches/notify.patch written by sd@ircnet. --- protocols/purple/purple.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 6a9472dc..3c1f505c 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * libpurple module - Main file * * * -* Copyright 2010 Wilmer van der Gaast * +* Copyright 2009-2010 Wilmer van der Gaast * * * * 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 * @@ -58,6 +58,7 @@ static void purple_init( account_t *acc ) PurplePluginProtocolInfo *pi = prpl->info->extra_info; PurpleAccount *pa; GList *i, *st; + set_t *s; /* Convert all protocol_options into per-account setting variables. */ for( i = pi->protocol_options; i; i = i->next ) @@ -66,7 +67,6 @@ static void purple_init( account_t *acc ) const char *name; char *def = NULL; set_eval eval = NULL; - set_t *s; name = purple_account_option_get_setting( o ); @@ -102,6 +102,12 @@ static void purple_init( account_t *acc ) } } + if( pi->options & OPT_PROTO_MAIL_CHECK ) + { + s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; + } + /* Go through all away states to figure out if away/status messages are possible. */ pa = purple_account_new( acc->user, (char*) acc->prpl->data ); @@ -158,6 +164,9 @@ static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) break; } } + + if( pi->options & OPT_PROTO_MAIL_CHECK ) + purple_account_set_check_mail( pa, set_getbool( &acc->set, "mail_notifications" ) ); } static void purple_login( account_t *acc ) @@ -237,7 +246,7 @@ static void purple_set_away( struct im_connection *ic, char *state_txt, char *me pst = st->data; if( state_txt == NULL && - purple_status_type_get_primitive( st->data ) == PURPLE_STATUS_AVAILABLE ) + purple_status_type_get_primitive( pst ) == PURPLE_STATUS_AVAILABLE ) break; if( state_txt != NULL && @@ -245,7 +254,7 @@ static void purple_set_away( struct im_connection *ic, char *state_txt, char *me break; } - if( message && purple_status_type_get_attr( st, "message" ) ) + if( message && purple_status_type_get_attr( pst, "message" ) ) { args = g_list_append( args, "message" ); args = g_list_append( args, message ); @@ -588,12 +597,29 @@ static PurpleEventLoopUiOps glib_eventloops = prplcb_ev_remove, }; +static void *prplcb_notify_email( PurpleConnection *gc, const char *subject, const char *from, + const char *to, const char *url ) +{ + struct im_connection *ic = purple_ic_by_gc( gc ); + + imcb_log( ic, "Received e-mail from %s for %s: %s <%s>", from, to, subject, url ); + + return NULL; +} + +static PurpleNotifyUiOps bee_notify_uiops = +{ + NULL, + prplcb_notify_email, +}; + static void purple_ui_init() { purple_blist_set_ui_ops( &bee_blist_uiops ); purple_connections_set_ui_ops( &bee_conn_uiops ); purple_conversations_set_ui_ops( &bee_conv_uiops ); purple_request_set_ui_ops( &bee_request_uiops ); + purple_notify_set_ui_ops(&bee_notify_uiops); //purple_debug_set_ui_ops( &bee_debug_uiops ); } @@ -643,6 +669,8 @@ void purple_initmodule() help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); + /* Add a protocol entry to BitlBee's structures for every protocol + supported by this libpurple instance. */ for( prots = purple_plugins_get_protocols(); prots; prots = prots->next ) { PurplePlugin *prot = prots->data; @@ -656,6 +684,8 @@ void purple_initmodule() g_string_append_printf( help, "\n* %s (%s)", ret->name, prot->info->name ); + /* libpurple doesn't define a protocol called OSCAR, but we + need it to be compatible with normal BitlBee. */ if( g_strcasecmp( prot->info->id, "prpl-aim" ) == 0 ) { ret = g_memdup( &funcs, sizeof( funcs ) ); @@ -665,6 +695,8 @@ void purple_initmodule() } } + /* Add a simple dynamically-generated help item listing all + the supported protocols. */ help_add_mem( &global.help, "purple", help->str ); g_string_free( help, TRUE ); } -- cgit v1.2.3 From 4dc6b8d10786baafd3ead9a2ecb22d7065b9c4b9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 12 Mar 2010 01:05:21 +0000 Subject: Added support for PURPLE_PREF_STRING_LIST style settings, this makes the QQ module (and maybe others) work. --- protocols/purple/purple.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 3c1f505c..9a6556b0 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -67,6 +67,9 @@ static void purple_init( account_t *acc ) const char *name; char *def = NULL; set_eval eval = NULL; + void *eval_data = NULL; + GList *io = NULL; + GSList *opts = NULL; name = purple_account_option_get_setting( o ); @@ -89,8 +92,20 @@ static void purple_init( account_t *acc ) eval = set_eval_bool; break; + case PURPLE_PREF_STRING_LIST: + def = g_strdup( purple_account_option_get_default_list_value( o ) ); + for( io = purple_account_option_get_list( o ); io; io = io->next ) + { + PurpleKeyValuePair *kv = io->data; + opts = g_slist_append( opts, kv->key ); + } + eval = set_eval_list; + eval_data = opts; + break; + default: - fprintf( stderr, "Setting with unknown type: %s (%d)\n", name, purple_account_option_get_type( o ) ); + irc_usermsg( acc->irc, "Setting with unknown type: %s (%d) Expect stuff to break..\n", + name, purple_account_option_get_type( o ) ); name = NULL; } @@ -98,6 +113,7 @@ static void purple_init( account_t *acc ) { s = set_add( &acc->set, name, def, eval, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; + s->eval_data = eval_data; g_free( def ); } } @@ -149,6 +165,7 @@ static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) switch( purple_account_option_get_type( o ) ) { case PURPLE_PREF_STRING: + case PURPLE_PREF_STRING_LIST: purple_account_set_string( pa, name, set_getstr( &acc->set, name ) ); break; -- cgit v1.2.3 From 7c5affcabd08f23e36719afefe736f266b80912b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 12 Mar 2010 01:47:44 +0000 Subject: Add some simple information about available settings to the online help command. --- protocols/purple/purple.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 9a6556b0..b336b108 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -59,6 +59,12 @@ static void purple_init( account_t *acc ) PurpleAccount *pa; GList *i, *st; set_t *s; + char help_title[64]; + GString *help; + + help = g_string_new( "" ); + g_string_printf( help, "BitlBee libpurple module %s (%s).\n\nSupported settings:", + (char*) acc->prpl->name, prpl->info->name ); /* Convert all protocol_options into per-account setting variables. */ for( i = pi->protocol_options; i; i = i->next ) @@ -77,11 +83,21 @@ static void purple_init( account_t *acc ) { case PURPLE_PREF_STRING: def = g_strdup( purple_account_option_get_default_string( o ) ); + + g_string_append_printf( help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text( o ), + "string", def ); + break; case PURPLE_PREF_INT: def = g_strdup_printf( "%d", purple_account_option_get_default_int( o ) ); eval = set_eval_int; + + g_string_append_printf( help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text( o ), + "integer", def ); + break; case PURPLE_PREF_BOOLEAN: @@ -90,17 +106,31 @@ static void purple_init( account_t *acc ) else def = g_strdup( "false" ); eval = set_eval_bool; + + g_string_append_printf( help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text( o ), + "boolean", def ); + break; case PURPLE_PREF_STRING_LIST: def = g_strdup( purple_account_option_get_default_list_value( o ) ); + + g_string_append_printf( help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text( o ), + "list", def ); + g_string_append( help, "\n Possible values: " ); + for( io = purple_account_option_get_list( o ); io; io = io->next ) { PurpleKeyValuePair *kv = io->data; opts = g_slist_append( opts, kv->key ); + g_string_append_printf( help, "%s, ", kv->key ); } + g_string_truncate( help, help->len - 2 ); eval = set_eval_list; eval_data = opts; + break; default: @@ -118,6 +148,10 @@ static void purple_init( account_t *acc ) } } + g_snprintf( help_title, sizeof( help_title ), "purple %s", (char*) acc->prpl->name ); + help_add_mem( &global.help, help_title, help->str ); + g_string_free( help, TRUE ); + if( pi->options & OPT_PROTO_MAIL_CHECK ) { s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); @@ -712,6 +746,9 @@ void purple_initmodule() } } + g_string_append( help, "\n\nFor used protocols, more information about available " + "settings can be found using \x02help purple \x02" ); + /* Add a simple dynamically-generated help item listing all the supported protocols. */ help_add_mem( &global.help, "purple", help->str ); -- cgit v1.2.3 From 437bd9b726339c44aa1a048cd84c2539bfa6cab5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 21 Mar 2010 21:38:42 +0000 Subject: Enough code to make an incoming transfer show up properly and accept it. Not enough yet to handle the incoming data. --- protocols/purple/purple.c | 65 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index b336b108..f0fc736e 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -580,12 +580,12 @@ static void *prplcb_request_action( const char *title, const char *primary, cons caption = va_arg( actions, char* ); fn = va_arg( actions, void* ); - if( strcmp( caption, "Accept" ) == 0 ) + if( strstr( caption, "Accept" ) ) { pqad->yes = fn; pqad->yes_i = i; } - else if( strcmp( caption, "Reject" ) == 0 ) + else if( strstr( caption, "Reject" ) || strstr( caption, "Cancel" ) ) { pqad->no = fn; pqad->no_i = i; @@ -658,20 +658,75 @@ static void *prplcb_notify_email( PurpleConnection *gc, const char *subject, con return NULL; } -static PurpleNotifyUiOps bee_notify_uiops = +static PurpleNotifyUiOps bee_notify_uiops = { NULL, prplcb_notify_email, }; +static void prplcb_xfer( PurpleXfer *xfer ) +{ + fprintf( stderr, "ft bla: 0x%p\n", xfer ); +} + +static void prpl_xfer_accept( struct file_transfer *ft ) +{ + purple_xfer_request_accepted( ft->data, NULL ); + purple_xfer_ui_ready( ft->data ); +} + +static void prpl_xfer_reject( struct file_transfer *ft ) +{ + purple_xfer_request_denied( ft->data ); +} + +static gboolean prplcb_xfer_new_cb( gpointer data, gint fd, b_input_condition cond ) +{ + PurpleXfer *xfer = data; + struct im_connection *ic = purple_ic_by_pa( xfer->account ); + file_transfer_t *ft; + + ft = imcb_file_send_start( ic, xfer->who, xfer->filename, xfer->size ); + ft->data = xfer; + xfer->ui_data = ft; + + ft->accept = prpl_xfer_accept; + + return FALSE; +} + +static void prplcb_xfer_new( PurpleXfer *xfer ) +{ + purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); + + fprintf( stderr, "ft_new bla: 0x%p\n", xfer ); + + b_timeout_add( 0, prplcb_xfer_new_cb, xfer ); +} + +static PurpleXferUiOps bee_xfer_uiops = +{ + prplcb_xfer_new, + prplcb_xfer, + prplcb_xfer, + prplcb_xfer, + prplcb_xfer, + prplcb_xfer, + prplcb_xfer, + prplcb_xfer, + prplcb_xfer, + prplcb_xfer, +}; + static void purple_ui_init() { purple_blist_set_ui_ops( &bee_blist_uiops ); purple_connections_set_ui_ops( &bee_conn_uiops ); purple_conversations_set_ui_ops( &bee_conv_uiops ); purple_request_set_ui_ops( &bee_request_uiops ); - purple_notify_set_ui_ops(&bee_notify_uiops); - //purple_debug_set_ui_ops( &bee_debug_uiops ); + purple_notify_set_ui_ops( &bee_notify_uiops ); + purple_xfers_set_ui_ops( &bee_xfer_uiops ); + purple_debug_set_ui_ops( &bee_debug_uiops ); } void purple_initmodule() -- cgit v1.2.3 From c735200e7727a7b17161c2a205ba6639d61e9b54 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 22 Mar 2010 01:20:40 +0000 Subject: Incoming file transfers can now be accepted (and should work) and/or rejected. Tested with Jabber and msn/msn-pecan so far. --- protocols/purple/purple.c | 90 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 23 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index f0fc736e..383ed55f 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -664,58 +664,102 @@ static PurpleNotifyUiOps bee_notify_uiops = prplcb_notify_email, }; -static void prplcb_xfer( PurpleXfer *xfer ) +struct prpl_xfer_data { - fprintf( stderr, "ft bla: 0x%p\n", xfer ); + PurpleXfer *xfer; + file_transfer_t *ft; + gint ready_timer; +}; + +/* Glorious hack: We seem to have to remind at least some libpurple plugins + that we're ready because this info may get lost if we give it too early. + So just do it ten times a second. :-/ */ +static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond ) +{ + purple_xfer_ui_ready( data ); + return TRUE; +} + +static gboolean prpl_xfer_write_request( struct file_transfer *ft ) +{ + struct prpl_xfer_data *px = ft->data; + px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px->xfer ); + return TRUE; +} + +static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size ) +{ + struct prpl_xfer_data *px = xfer->ui_data; + gboolean st; + + b_event_remove( px->ready_timer ); + px->ready_timer = 0; + + st = px->ft->write( px->ft, (char*) buffer, size ); + + if( st && xfer->bytes_remaining == size ) + imcb_file_finished( px->ft ); + + return st ? size : 0; } static void prpl_xfer_accept( struct file_transfer *ft ) { - purple_xfer_request_accepted( ft->data, NULL ); - purple_xfer_ui_ready( ft->data ); + struct prpl_xfer_data *px = ft->data; + purple_xfer_request_accepted( px->xfer, NULL ); + prpl_xfer_write_request( ft ); } -static void prpl_xfer_reject( struct file_transfer *ft ) +static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) { - purple_xfer_request_denied( ft->data ); + struct prpl_xfer_data *px = ft->data; + purple_xfer_request_denied( px->xfer ); } static gboolean prplcb_xfer_new_cb( gpointer data, gint fd, b_input_condition cond ) { PurpleXfer *xfer = data; struct im_connection *ic = purple_ic_by_pa( xfer->account ); - file_transfer_t *ft; + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + PurpleBuddy *buddy; + const char *who; + + buddy = purple_find_buddy( xfer->account, xfer->who ); + who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; - ft = imcb_file_send_start( ic, xfer->who, xfer->filename, xfer->size ); - ft->data = xfer; - xfer->ui_data = ft; + /* TODO(wilmer): After spreading some more const goodness in BitlBee, + remove the evil cast below. */ + px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); + px->ft->data = px; + px->xfer = data; + px->xfer->ui_data = px; - ft->accept = prpl_xfer_accept; + px->ft->accept = prpl_xfer_accept; + px->ft->canceled = prpl_xfer_canceled; + px->ft->write_request = prpl_xfer_write_request; return FALSE; } static void prplcb_xfer_new( PurpleXfer *xfer ) { + /* This should suppress the stupid file dialog. */ purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); - fprintf( stderr, "ft_new bla: 0x%p\n", xfer ); - + /* Sadly the xfer struct is still empty ATM so come back after + the caller is done. */ b_timeout_add( 0, prplcb_xfer_new_cb, xfer ); } static PurpleXferUiOps bee_xfer_uiops = { prplcb_xfer_new, - prplcb_xfer, - prplcb_xfer, - prplcb_xfer, - prplcb_xfer, - prplcb_xfer, - prplcb_xfer, - prplcb_xfer, - prplcb_xfer, - prplcb_xfer, + NULL, + NULL, + NULL, + NULL, + NULL, + prplcb_xfer_write, }; static void purple_ui_init() @@ -726,7 +770,7 @@ static void purple_ui_init() purple_request_set_ui_ops( &bee_request_uiops ); purple_notify_set_ui_ops( &bee_notify_uiops ); purple_xfers_set_ui_ops( &bee_xfer_uiops ); - purple_debug_set_ui_ops( &bee_debug_uiops ); + //purple_debug_set_ui_ops( &bee_debug_uiops ); } void purple_initmodule() -- cgit v1.2.3 From edfc6db1415558b7f202cc3fa2654ad58defea78 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 23 Mar 2010 01:06:25 +0000 Subject: Frankenstein, it lives! This stuff can send files but it has troubles with certain protocol modules, don't rely on this yet. It's also getting too messy and should be split off into a separate file. --- protocols/purple/purple.c | 133 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 15 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 383ed55f..997b09f7 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -364,6 +364,8 @@ static int purple_send_typing( struct im_connection *ic, char *who, int flags ) } } +void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ); + static void purple_ui_init(); static PurpleCoreUiOps bee_core_uiops = @@ -664,26 +666,34 @@ static PurpleNotifyUiOps bee_notify_uiops = prplcb_notify_email, }; + struct prpl_xfer_data { PurpleXfer *xfer; file_transfer_t *ft; gint ready_timer; + char *buf; + int buf_len; }; +static file_transfer_t *next_ft; + /* Glorious hack: We seem to have to remind at least some libpurple plugins that we're ready because this info may get lost if we give it too early. So just do it ten times a second. :-/ */ static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond ) { - purple_xfer_ui_ready( data ); - return TRUE; + struct prpl_xfer_data *px = data; + + purple_xfer_ui_ready( px->xfer ); + + return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE; } static gboolean prpl_xfer_write_request( struct file_transfer *ft ) { struct prpl_xfer_data *px = ft->data; - px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px->xfer ); + px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px ); return TRUE; } @@ -703,6 +713,19 @@ static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize return st ? size : 0; } +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +{ + struct prpl_xfer_data *px = ft->data; + + px->buf = g_memdup( buffer, len ); + px->buf_len = len; + + //purple_xfer_ui_ready( px->xfer ); + px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px ); + + return TRUE; +} + static void prpl_xfer_accept( struct file_transfer *ft ) { struct prpl_xfer_data *px = ft->data; @@ -716,7 +739,7 @@ static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) purple_xfer_request_denied( px->xfer ); } -static gboolean prplcb_xfer_new_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) { PurpleXfer *xfer = data; struct im_connection *ic = purple_ic_by_pa( xfer->account ); @@ -743,25 +766,103 @@ static gboolean prplcb_xfer_new_cb( gpointer data, gint fd, b_input_condition co static void prplcb_xfer_new( PurpleXfer *xfer ) { - /* This should suppress the stupid file dialog. */ - purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); + if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) + { + /* This should suppress the stupid file dialog. */ + purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); + + /* Sadly the xfer struct is still empty ATM so come back after + the caller is done. */ + b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); + } + else + { + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + + px->ft = next_ft; + px->ft->data = px; + px->xfer = xfer; + px->xfer->ui_data = px; + + purple_xfer_set_filename( xfer, px->ft->file_name ); + purple_xfer_set_size( xfer, px->ft->file_size ); + + next_ft = NULL; + } +} + +static void prplcb_xfer_dbg( PurpleXfer *xfer ) +{ + fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); +} + +gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size ) +{ + struct prpl_xfer_data *px = xfer->ui_data; - /* Sadly the xfer struct is still empty ATM so come back after - the caller is done. */ - b_timeout_add( 0, prplcb_xfer_new_cb, xfer ); + fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len ); + + if( px->buf ) + { + *buffer = px->buf; + px->buf = NULL; + + px->ft->write_request( px->ft ); + + return px->buf_len; + } + + return 0; } static PurpleXferUiOps bee_xfer_uiops = { prplcb_xfer_new, - NULL, - NULL, - NULL, - NULL, - NULL, + prplcb_xfer_dbg, + prplcb_xfer_dbg, + prplcb_xfer_dbg, + prplcb_xfer_dbg, + prplcb_xfer_dbg, prplcb_xfer_write, + prplcb_xfer_read, + prplcb_xfer_dbg, }; +static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ); + +void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) +{ + PurpleAccount *pa = ic->proto_data; + struct prpl_xfer_data *px; + + /* xfer_new() will pick up this variable. It's a hack but we're not + multi-threaded anyway. */ + next_ft = ft; + serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name ); + + ft->write = prpl_xfer_write; + + px = ft->data; + imcb_file_recv_start( ft ); + + px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px ); +} + +static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ) +{ + struct prpl_xfer_data *px = data; + + if( px->ft->status & FT_STATUS_TRANSFERRING ) + { + fprintf( stderr, "The ft, it is ready...\n" ); + px->ft->write_request( px->ft ); + + return FALSE; + } + + return TRUE; +} + static void purple_ui_init() { purple_blist_set_ui_ops( &bee_blist_uiops ); @@ -770,7 +871,7 @@ static void purple_ui_init() purple_request_set_ui_ops( &bee_request_uiops ); purple_notify_set_ui_ops( &bee_notify_uiops ); purple_xfers_set_ui_ops( &bee_xfer_uiops ); - //purple_debug_set_ui_ops( &bee_debug_uiops ); + purple_debug_set_ui_ops( &bee_debug_uiops ); } void purple_initmodule() @@ -816,6 +917,8 @@ void purple_initmodule() funcs.keepalive = purple_keepalive; funcs.send_typing = purple_send_typing; funcs.handle_cmp = g_strcasecmp; + /* TODO(wilmer): Set this one only for protocols that support it? */ + funcs.transfer_request = purple_transfer_request; help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); -- cgit v1.2.3 From a897467549fc75eee8fdd7c255ee5f55c3714ac6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 18 Apr 2010 00:43:55 +0200 Subject: I should stop doing commits with the debugging stuff still enabled. --- protocols/purple/purple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 997b09f7..44a21fae 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -871,7 +871,7 @@ static void purple_ui_init() purple_request_set_ui_ops( &bee_request_uiops ); purple_notify_set_ui_ops( &bee_notify_uiops ); purple_xfers_set_ui_ops( &bee_xfer_uiops ); - purple_debug_set_ui_ops( &bee_debug_uiops ); + //purple_debug_set_ui_ops( &bee_debug_uiops ); } void purple_initmodule() -- cgit v1.2.3 From f4850088ea8527d8cfd46dedea678bb0d5d93471 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 May 2010 00:55:48 +0100 Subject: Support at least incoming groupchats. Not sure yet how starting them is going to work. --- protocols/purple/purple.c | 78 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 44a21fae..b81415ea 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -364,6 +364,13 @@ static int purple_send_typing( struct im_connection *ic, char *who, int flags ) } } +static void purple_chat_msg( struct groupchat *gc, char *message, int flags ) +{ + PurpleConversation *pc = gc->data; + + purple_conv_chat_send( purple_conversation_get_chat_data( pc ), message ); +} + void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ); static void purple_ui_init(); @@ -505,6 +512,64 @@ static PurpleBlistUiOps bee_blist_uiops = prplcb_blist_remove, }; +void prplcb_conv_new( PurpleConversation *conv ) +{ + if( conv->type == PURPLE_CONV_TYPE_CHAT ) + { + struct im_connection *ic = purple_ic_by_pa( conv->account ); + struct groupchat *gc; + + gc = imcb_chat_new( ic, conv->name ); + conv->ui_data = gc; + gc->data = conv; + } +} + +void prplcb_conv_free( PurpleConversation *conv ) +{ + struct groupchat *gc = conv->ui_data; + + imcb_chat_free( gc ); +} + +void prplcb_conv_add_users( PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals ) +{ + struct groupchat *gc = conv->ui_data; + GList *b; + + for( b = cbuddies; b; b = b->next ) + { + PurpleConvChatBuddy *pcb = b->data; + + imcb_chat_add_buddy( gc, pcb->name ); + } +} + +void prplcb_conv_del_users( PurpleConversation *conv, GList *cbuddies ) +{ + struct groupchat *gc = conv->ui_data; + GList *b; + + for( b = cbuddies; b; b = b->next ) + imcb_chat_remove_buddy( gc, b->data, "" ); +} + +void prplcb_conv_chat_msg( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) +{ + struct groupchat *gc = conv->ui_data; + PurpleBuddy *buddy; + + /* ..._SEND means it's an outgoing message, no need to echo those. */ + if( flags & PURPLE_MESSAGE_SEND ) + return; + + buddy = purple_find_buddy( conv->account, who ); + if( buddy != NULL ) + who = purple_buddy_get_name( buddy ); + + imcb_chat_msg( gc, who, (char*) message, 0, mtime ); +} + static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) { struct im_connection *ic = purple_ic_by_pa( conv->account ); @@ -523,14 +588,14 @@ static void prplcb_conv_im( PurpleConversation *conv, const char *who, const cha static PurpleConversationUiOps bee_conv_uiops = { - NULL, /* create_conversation */ - NULL, /* destroy_conversation */ - NULL, /* write_chat */ + prplcb_conv_new, /* create_conversation */ + prplcb_conv_free, /* destroy_conversation */ + prplcb_conv_chat_msg, /* write_chat */ prplcb_conv_im, /* write_im */ NULL, /* write_conv */ - NULL, /* chat_add_users */ + prplcb_conv_add_users, /* chat_add_users */ NULL, /* chat_rename_user */ - NULL, /* chat_remove_users */ + prplcb_conv_del_users, /* chat_remove_users */ NULL, /* chat_update_user */ NULL, /* present */ NULL, /* has_focus */ @@ -917,7 +982,8 @@ void purple_initmodule() funcs.keepalive = purple_keepalive; funcs.send_typing = purple_send_typing; funcs.handle_cmp = g_strcasecmp; - /* TODO(wilmer): Set this one only for protocols that support it? */ + /* TODO(wilmer): Set these only for protocols that support them? */ + funcs.chat_msg = purple_chat_msg; funcs.transfer_request = purple_transfer_request; help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); -- cgit v1.2.3 From 8ad5c34dfc1eff0112f73414fd4b566fae0c9ce3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 May 2010 16:53:18 +0100 Subject: Added support for creating groupchats. This can only be done in a horribly broken way which is surely going to break somehow someday. --- protocols/purple/purple.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index b81415ea..0f60f630 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -52,6 +52,22 @@ static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) return purple_ic_by_pa( purple_connection_get_account( gc ) ); } +static gboolean purple_menu_cmp( const char *a, const char *b ) +{ + while( *a && *b ) + { + while( *a == '_' ) a ++; + while( *b == '_' ) b ++; + if( tolower( *a ) != tolower( *b ) ) + return FALSE; + + a ++; + b ++; + } + + return ( *a == '\0' && *b == '\0' ); +} + static void purple_init( account_t *acc ) { PurplePlugin *prpl = purple_plugins_find_with_id( (char*) acc->prpl->data ); @@ -371,6 +387,67 @@ static void purple_chat_msg( struct groupchat *gc, char *message, int flags ) purple_conv_chat_send( purple_conversation_get_chat_data( pc ), message ); } +struct groupchat *purple_chat_with( struct im_connection *ic, char *who ) +{ + /* No, "of course" this won't work this way. Or in fact, it almost + does, but it only lets you send msgs to it, you won't receive + any. Instead, we have to click the virtual menu item. + PurpleAccount *pa = ic->proto_data; + PurpleConversation *pc; + PurpleConvChat *pcc; + struct groupchat *gc; + + gc = imcb_chat_new( ic, "BitlBee-libpurple groupchat" ); + gc->data = pc = purple_conversation_new( PURPLE_CONV_TYPE_CHAT, pa, "BitlBee-libpurple groupchat" ); + pc->ui_data = gc; + + pcc = PURPLE_CONV_CHAT( pc ); + purple_conv_chat_add_user( pcc, ic->acc->user, "", 0, TRUE ); + purple_conv_chat_invite_user( pcc, who, "Please join my chat", FALSE ); + //purple_conv_chat_add_user( pcc, who, "", 0, TRUE ); + */ + + /* There went my nice afternoon. :-( */ + + PurpleAccount *pa = ic->proto_data; + PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id ); + PurplePluginProtocolInfo *pi = prpl->info->extra_info; + PurpleBuddy *pb = purple_find_buddy( (PurpleAccount*) ic->proto_data, who ); + PurpleMenuAction *mi; + GList *menu; + void (*callback)(PurpleBlistNode *, gpointer); /* FFFFFFFFFFFFFUUUUUUUUUUUUUU */ + + if( !pb || !pi || !pi->blist_node_menu ) + return NULL; + + menu = pi->blist_node_menu( &pb->node ); + while( menu ) + { + mi = menu->data; + if( purple_menu_cmp( mi->label, "initiate chat" ) || + purple_menu_cmp( mi->label, "initiate conference" ) ) + break; + menu = menu->next; + } + + if( menu == NULL ) + return NULL; + + /* Call the fucker. */ + callback = (void*) mi->callback; + callback( &pb->node, menu->data ); + + return NULL; +} + +void purple_chat_invite( struct groupchat *gc, char *who, char *message ) +{ + PurpleConversation *pc = gc->data; + PurpleConvChat *pcc = PURPLE_CONV_CHAT( pc ); + + purple_conv_chat_invite_user( pcc, who, message && *message ? message : "Please join my chat", FALSE ); +} + void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ); static void purple_ui_init(); @@ -537,6 +614,14 @@ void prplcb_conv_add_users( PurpleConversation *conv, GList *cbuddies, gboolean struct groupchat *gc = conv->ui_data; GList *b; + if( !gc->joined && strcmp( conv->account->protocol_id, "prpl-msn" ) == 0 ) + { + /* Work around the broken MSN module which fucks up the user's + handle completely when informing him/her that he just + successfully joined the room s/he just created (v2.6.6). */ + imcb_chat_add_buddy( gc, gc->ic->acc->user ); + } + for( b = cbuddies; b; b = b->next ) { PurpleConvChatBuddy *pcb = b->data; @@ -984,6 +1069,8 @@ void purple_initmodule() funcs.handle_cmp = g_strcasecmp; /* TODO(wilmer): Set these only for protocols that support them? */ funcs.chat_msg = purple_chat_msg; + funcs.chat_with = purple_chat_with; + funcs.chat_invite = purple_chat_invite; funcs.transfer_request = purple_transfer_request; help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); -- cgit v1.2.3 From 15794dcafac99b2be1c400bc54a510fe61c4ebac Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 May 2010 17:03:41 +0100 Subject: Groupchat support "finished". Named chatrooms are not supported yet. This only adds support for the "chat with" command and for getting pulled into other people's chats. --- protocols/purple/purple.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 0f60f630..90312d0d 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -448,6 +448,13 @@ void purple_chat_invite( struct groupchat *gc, char *who, char *message ) purple_conv_chat_invite_user( pcc, who, message && *message ? message : "Please join my chat", FALSE ); } +void purple_chat_leave( struct groupchat *gc, char *who ) +{ + PurpleConversation *pc = gc->data; + + purple_conversation_destroy( pc ); +} + void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ); static void purple_ui_init(); @@ -1071,6 +1078,7 @@ void purple_initmodule() funcs.chat_msg = purple_chat_msg; funcs.chat_with = purple_chat_with; funcs.chat_invite = purple_chat_invite; + funcs.chat_leave = purple_chat_leave; funcs.transfer_request = purple_transfer_request; help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); -- cgit v1.2.3 From d8acfd3ba84e018554d8564f08e9a50cde56b4a4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 10 May 2010 00:23:34 +0100 Subject: Purple lists mix up key and value; key == what the user sees, *value* is what the module understands. This should hopefully resolve QQ issues. --- protocols/purple/purple.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 90312d0d..edd10219 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -140,8 +140,11 @@ static void purple_init( account_t *acc ) for( io = purple_account_option_get_list( o ); io; io = io->next ) { PurpleKeyValuePair *kv = io->data; - opts = g_slist_append( opts, kv->key ); - g_string_append_printf( help, "%s, ", kv->key ); + opts = g_slist_append( opts, kv->value ); + if( strcmp( kv->value, kv->key ) != 0 ) + g_string_append_printf( help, "%s (%s), ", kv->value, kv->key ); + else + g_string_append_printf( help, "%s, ", kv->value ); } g_string_truncate( help, help->len - 2 ); eval = set_eval_list; -- cgit v1.2.3 From 2309152972f1d52af6adbb0e7e5d9c5ad3ae80f9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 17 May 2010 01:14:14 +0100 Subject: Split off the file transfer stuff into a separate file. What a mess. --- protocols/purple/Makefile | 2 +- protocols/purple/ft.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++ protocols/purple/purple.c | 199 +-------------------------------------- 3 files changed, 237 insertions(+), 198 deletions(-) create mode 100644 protocols/purple/ft.c (limited to 'protocols') diff --git a/protocols/purple/Makefile b/protocols/purple/Makefile index 15460529..403db799 100644 --- a/protocols/purple/Makefile +++ b/protocols/purple/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = purple.o +objects = ft.o purple.o CFLAGS += -Wall $(PURPLE_CFLAGS) LFLAGS += -r diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c new file mode 100644 index 00000000..62a1092a --- /dev/null +++ b/protocols/purple/ft.c @@ -0,0 +1,234 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* libpurple module - File transfer stuff * +* * +* Copyright 2009-2010 Wilmer van der Gaast * +* * +* 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 along * +* with this program; if not, write to the Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "bitlbee.h" + +#include + +#include +#include + +struct prpl_xfer_data +{ + PurpleXfer *xfer; + file_transfer_t *ft; + gint ready_timer; + char *buf; + int buf_len; +}; + +static file_transfer_t *next_ft; + +struct im_connection *purple_ic_by_pa( PurpleAccount *pa ); + +/* Glorious hack: We seem to have to remind at least some libpurple plugins + that we're ready because this info may get lost if we give it too early. + So just do it ten times a second. :-/ */ +static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond ) +{ + struct prpl_xfer_data *px = data; + + purple_xfer_ui_ready( px->xfer ); + + return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE; +} + +static gboolean prpl_xfer_write_request( struct file_transfer *ft ) +{ + struct prpl_xfer_data *px = ft->data; + px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px ); + return TRUE; +} + +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +{ + struct prpl_xfer_data *px = ft->data; + + px->buf = g_memdup( buffer, len ); + px->buf_len = len; + + //purple_xfer_ui_ready( px->xfer ); + px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px ); + + return TRUE; +} + +static void prpl_xfer_accept( struct file_transfer *ft ) +{ + struct prpl_xfer_data *px = ft->data; + purple_xfer_request_accepted( px->xfer, NULL ); + prpl_xfer_write_request( ft ); +} + +static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) +{ + struct prpl_xfer_data *px = ft->data; + purple_xfer_request_denied( px->xfer ); +} + +static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) +{ + PurpleXfer *xfer = data; + struct im_connection *ic = purple_ic_by_pa( xfer->account ); + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + PurpleBuddy *buddy; + const char *who; + + buddy = purple_find_buddy( xfer->account, xfer->who ); + who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; + + /* TODO(wilmer): After spreading some more const goodness in BitlBee, + remove the evil cast below. */ + px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); + px->ft->data = px; + px->xfer = data; + px->xfer->ui_data = px; + + px->ft->accept = prpl_xfer_accept; + px->ft->canceled = prpl_xfer_canceled; + px->ft->write_request = prpl_xfer_write_request; + + return FALSE; +} + +static void prplcb_xfer_new( PurpleXfer *xfer ) +{ + if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) + { + /* This should suppress the stupid file dialog. */ + purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); + + /* Sadly the xfer struct is still empty ATM so come back after + the caller is done. */ + b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); + } + else + { + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + + px->ft = next_ft; + px->ft->data = px; + px->xfer = xfer; + px->xfer->ui_data = px; + + purple_xfer_set_filename( xfer, px->ft->file_name ); + purple_xfer_set_size( xfer, px->ft->file_size ); + + next_ft = NULL; + } +} + +static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) +{ + fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent ); +} + +static void prplcb_xfer_dbg( PurpleXfer *xfer ) +{ + fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); +} + +static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size ) +{ + struct prpl_xfer_data *px = xfer->ui_data; + gboolean st; + + fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len ); + + b_event_remove( px->ready_timer ); + px->ready_timer = 0; + + st = px->ft->write( px->ft, (char*) buffer, size ); + + if( st && xfer->bytes_remaining == size ) + imcb_file_finished( px->ft ); + + return st ? size : 0; +} + +gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size ) +{ + struct prpl_xfer_data *px = xfer->ui_data; + + fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len ); + + if( px->buf ) + { + *buffer = px->buf; + px->buf = NULL; + + px->ft->write_request( px->ft ); + + return px->buf_len; + } + + return 0; +} + +PurpleXferUiOps bee_xfer_uiops = +{ + prplcb_xfer_new, + prplcb_xfer_dbg, + prplcb_xfer_dbg, + prplcb_xfer_progress, + prplcb_xfer_dbg, + prplcb_xfer_dbg, + prplcb_xfer_write, + prplcb_xfer_read, + prplcb_xfer_dbg, +}; + +static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ); + +void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) +{ + PurpleAccount *pa = ic->proto_data; + struct prpl_xfer_data *px; + + /* xfer_new() will pick up this variable. It's a hack but we're not + multi-threaded anyway. */ + next_ft = ft; + serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name ); + + ft->write = prpl_xfer_write; + + px = ft->data; + imcb_file_recv_start( ft ); + + px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px ); +} + +static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ) +{ + struct prpl_xfer_data *px = data; + + if( px->ft->status & FT_STATUS_TRANSFERRING ) + { + fprintf( stderr, "The ft, it is ready...\n" ); + px->ft->write_request( px->ft ); + + return FALSE; + } + + return TRUE; +} diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index edd10219..b01fb991 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -36,7 +36,7 @@ GSList *purple_connections; libpurple in daemon mode anyway. */ static irc_t *local_irc; -static struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) +struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) { GSList *i; @@ -826,202 +826,7 @@ static PurpleNotifyUiOps bee_notify_uiops = prplcb_notify_email, }; - -struct prpl_xfer_data -{ - PurpleXfer *xfer; - file_transfer_t *ft; - gint ready_timer; - char *buf; - int buf_len; -}; - -static file_transfer_t *next_ft; - -/* Glorious hack: We seem to have to remind at least some libpurple plugins - that we're ready because this info may get lost if we give it too early. - So just do it ten times a second. :-/ */ -static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond ) -{ - struct prpl_xfer_data *px = data; - - purple_xfer_ui_ready( px->xfer ); - - return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE; -} - -static gboolean prpl_xfer_write_request( struct file_transfer *ft ) -{ - struct prpl_xfer_data *px = ft->data; - px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px ); - return TRUE; -} - -static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size ) -{ - struct prpl_xfer_data *px = xfer->ui_data; - gboolean st; - - b_event_remove( px->ready_timer ); - px->ready_timer = 0; - - st = px->ft->write( px->ft, (char*) buffer, size ); - - if( st && xfer->bytes_remaining == size ) - imcb_file_finished( px->ft ); - - return st ? size : 0; -} - -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) -{ - struct prpl_xfer_data *px = ft->data; - - px->buf = g_memdup( buffer, len ); - px->buf_len = len; - - //purple_xfer_ui_ready( px->xfer ); - px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px ); - - return TRUE; -} - -static void prpl_xfer_accept( struct file_transfer *ft ) -{ - struct prpl_xfer_data *px = ft->data; - purple_xfer_request_accepted( px->xfer, NULL ); - prpl_xfer_write_request( ft ); -} - -static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) -{ - struct prpl_xfer_data *px = ft->data; - purple_xfer_request_denied( px->xfer ); -} - -static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) -{ - PurpleXfer *xfer = data; - struct im_connection *ic = purple_ic_by_pa( xfer->account ); - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); - PurpleBuddy *buddy; - const char *who; - - buddy = purple_find_buddy( xfer->account, xfer->who ); - who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; - - /* TODO(wilmer): After spreading some more const goodness in BitlBee, - remove the evil cast below. */ - px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); - px->ft->data = px; - px->xfer = data; - px->xfer->ui_data = px; - - px->ft->accept = prpl_xfer_accept; - px->ft->canceled = prpl_xfer_canceled; - px->ft->write_request = prpl_xfer_write_request; - - return FALSE; -} - -static void prplcb_xfer_new( PurpleXfer *xfer ) -{ - if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) - { - /* This should suppress the stupid file dialog. */ - purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); - - /* Sadly the xfer struct is still empty ATM so come back after - the caller is done. */ - b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); - } - else - { - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); - - px->ft = next_ft; - px->ft->data = px; - px->xfer = xfer; - px->xfer->ui_data = px; - - purple_xfer_set_filename( xfer, px->ft->file_name ); - purple_xfer_set_size( xfer, px->ft->file_size ); - - next_ft = NULL; - } -} - -static void prplcb_xfer_dbg( PurpleXfer *xfer ) -{ - fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); -} - -gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size ) -{ - struct prpl_xfer_data *px = xfer->ui_data; - - fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len ); - - if( px->buf ) - { - *buffer = px->buf; - px->buf = NULL; - - px->ft->write_request( px->ft ); - - return px->buf_len; - } - - return 0; -} - -static PurpleXferUiOps bee_xfer_uiops = -{ - prplcb_xfer_new, - prplcb_xfer_dbg, - prplcb_xfer_dbg, - prplcb_xfer_dbg, - prplcb_xfer_dbg, - prplcb_xfer_dbg, - prplcb_xfer_write, - prplcb_xfer_read, - prplcb_xfer_dbg, -}; - -static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ); - -void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) -{ - PurpleAccount *pa = ic->proto_data; - struct prpl_xfer_data *px; - - /* xfer_new() will pick up this variable. It's a hack but we're not - multi-threaded anyway. */ - next_ft = ft; - serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name ); - - ft->write = prpl_xfer_write; - - px = ft->data; - imcb_file_recv_start( ft ); - - px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px ); -} - -static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ) -{ - struct prpl_xfer_data *px = data; - - if( px->ft->status & FT_STATUS_TRANSFERRING ) - { - fprintf( stderr, "The ft, it is ready...\n" ); - px->ft->write_request( px->ft ); - - return FALSE; - } - - return TRUE; -} +extern PurpleXferUiOps bee_xfer_uiops; static void purple_ui_init() { -- cgit v1.2.3 From 553767cacf43e1a4a1038530c47dc0af5fdd0369 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 17 May 2010 21:30:45 +0100 Subject: Move direct ft stuff to an unused file: This gets too hairy and too fragile. I don't have time to work out all the details, I doubt if this is supposed to work reliably yet at all. Let's go for the simple via-disk approach for now. --- protocols/purple/ft-direct.c | 239 +++++++++++++++++++++++++++++++++++++++++++ protocols/purple/ft.c | 137 +++++++------------------ 2 files changed, 275 insertions(+), 101 deletions(-) create mode 100644 protocols/purple/ft-direct.c (limited to 'protocols') diff --git a/protocols/purple/ft-direct.c b/protocols/purple/ft-direct.c new file mode 100644 index 00000000..98a16d75 --- /dev/null +++ b/protocols/purple/ft-direct.c @@ -0,0 +1,239 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* libpurple module - File transfer stuff * +* * +* Copyright 2009-2010 Wilmer van der Gaast * +* * +* 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 along * +* with this program; if not, write to the Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +\***************************************************************************/ + +/* This code tries to do direct file transfers, i.e. without caching the file + locally on disk first. Since libpurple can only do this since version 2.6.0 + and even then very unreliably (and not with all IM modules), I'm canning + this code for now. */ + +#include "bitlbee.h" + +#include + +#include +#include + +struct prpl_xfer_data +{ + PurpleXfer *xfer; + file_transfer_t *ft; + gint ready_timer; + char *buf; + int buf_len; +}; + +static file_transfer_t *next_ft; + +struct im_connection *purple_ic_by_pa( PurpleAccount *pa ); + +/* Glorious hack: We seem to have to remind at least some libpurple plugins + that we're ready because this info may get lost if we give it too early. + So just do it ten times a second. :-/ */ +static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond ) +{ + struct prpl_xfer_data *px = data; + + purple_xfer_ui_ready( px->xfer ); + + return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE; +} + +static gboolean prpl_xfer_write_request( struct file_transfer *ft ) +{ + struct prpl_xfer_data *px = ft->data; + px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px ); + return TRUE; +} + +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +{ + struct prpl_xfer_data *px = ft->data; + + px->buf = g_memdup( buffer, len ); + px->buf_len = len; + + //purple_xfer_ui_ready( px->xfer ); + px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px ); + + return TRUE; +} + +static void prpl_xfer_accept( struct file_transfer *ft ) +{ + struct prpl_xfer_data *px = ft->data; + purple_xfer_request_accepted( px->xfer, NULL ); + prpl_xfer_write_request( ft ); +} + +static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) +{ + struct prpl_xfer_data *px = ft->data; + purple_xfer_request_denied( px->xfer ); +} + +static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) +{ + PurpleXfer *xfer = data; + struct im_connection *ic = purple_ic_by_pa( xfer->account ); + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + PurpleBuddy *buddy; + const char *who; + + buddy = purple_find_buddy( xfer->account, xfer->who ); + who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; + + /* TODO(wilmer): After spreading some more const goodness in BitlBee, + remove the evil cast below. */ + px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); + px->ft->data = px; + px->xfer = data; + px->xfer->ui_data = px; + + px->ft->accept = prpl_xfer_accept; + px->ft->canceled = prpl_xfer_canceled; + px->ft->write_request = prpl_xfer_write_request; + + return FALSE; +} + +static void prplcb_xfer_new( PurpleXfer *xfer ) +{ + if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) + { + /* This should suppress the stupid file dialog. */ + purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); + + /* Sadly the xfer struct is still empty ATM so come back after + the caller is done. */ + b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); + } + else + { + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + + px->ft = next_ft; + px->ft->data = px; + px->xfer = xfer; + px->xfer->ui_data = px; + + purple_xfer_set_filename( xfer, px->ft->file_name ); + purple_xfer_set_size( xfer, px->ft->file_size ); + + next_ft = NULL; + } +} + +static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) +{ + fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent ); +} + +static void prplcb_xfer_dbg( PurpleXfer *xfer ) +{ + fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); +} + +static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size ) +{ + struct prpl_xfer_data *px = xfer->ui_data; + gboolean st; + + fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len ); + + b_event_remove( px->ready_timer ); + px->ready_timer = 0; + + st = px->ft->write( px->ft, (char*) buffer, size ); + + if( st && xfer->bytes_remaining == size ) + imcb_file_finished( px->ft ); + + return st ? size : 0; +} + +gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size ) +{ + struct prpl_xfer_data *px = xfer->ui_data; + + fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len ); + + if( px->buf ) + { + *buffer = px->buf; + px->buf = NULL; + + px->ft->write_request( px->ft ); + + return px->buf_len; + } + + return 0; +} + +PurpleXferUiOps bee_xfer_uiops = +{ + prplcb_xfer_new, + prplcb_xfer_dbg, + prplcb_xfer_dbg, + prplcb_xfer_progress, + prplcb_xfer_dbg, + prplcb_xfer_dbg, + prplcb_xfer_write, + prplcb_xfer_read, + prplcb_xfer_dbg, +}; + +static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ); + +void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) +{ + PurpleAccount *pa = ic->proto_data; + struct prpl_xfer_data *px; + + /* xfer_new() will pick up this variable. It's a hack but we're not + multi-threaded anyway. */ + next_ft = ft; + serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name ); + + ft->write = prpl_xfer_write; + + px = ft->data; + imcb_file_recv_start( ft ); + + px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px ); +} + +static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ) +{ + struct prpl_xfer_data *px = data; + + if( px->ft->status & FT_STATUS_TRANSFERRING ) + { + fprintf( stderr, "The ft, it is ready...\n" ); + px->ft->write_request( px->ft ); + + return FALSE; + } + + return TRUE; +} diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c index 62a1092a..4b5a3f49 100644 --- a/protocols/purple/ft.c +++ b/protocols/purple/ft.c @@ -21,6 +21,11 @@ * * \***************************************************************************/ +/* Do file transfers via disk for now, since libpurple was really designed + for straight-to/from disk fts and is only just learning how to pass the + file contents the the UI instead (2.6.0 and higher it seems, and with + varying levels of success). */ + #include "bitlbee.h" #include @@ -41,36 +46,16 @@ static file_transfer_t *next_ft; struct im_connection *purple_ic_by_pa( PurpleAccount *pa ); -/* Glorious hack: We seem to have to remind at least some libpurple plugins - that we're ready because this info may get lost if we give it too early. - So just do it ten times a second. :-/ */ -static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond ) -{ - struct prpl_xfer_data *px = data; - - purple_xfer_ui_ready( px->xfer ); - - return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE; -} - static gboolean prpl_xfer_write_request( struct file_transfer *ft ) { - struct prpl_xfer_data *px = ft->data; - px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px ); - return TRUE; + return FALSE; } static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) { struct prpl_xfer_data *px = ft->data; - px->buf = g_memdup( buffer, len ); - px->buf_len = len; - - //purple_xfer_ui_ready( px->xfer ); - px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px ); - - return TRUE; + return FALSE; } static void prpl_xfer_accept( struct file_transfer *ft ) @@ -86,30 +71,7 @@ static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) purple_xfer_request_denied( px->xfer ); } -static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) -{ - PurpleXfer *xfer = data; - struct im_connection *ic = purple_ic_by_pa( xfer->account ); - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); - PurpleBuddy *buddy; - const char *who; - - buddy = purple_find_buddy( xfer->account, xfer->who ); - who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; - - /* TODO(wilmer): After spreading some more const goodness in BitlBee, - remove the evil cast below. */ - px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); - px->ft->data = px; - px->xfer = data; - px->xfer->ui_data = px; - - px->ft->accept = prpl_xfer_accept; - px->ft->canceled = prpl_xfer_canceled; - px->ft->write_request = prpl_xfer_write_request; - - return FALSE; -} +static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ); static void prplcb_xfer_new( PurpleXfer *xfer ) { @@ -124,6 +86,7 @@ static void prplcb_xfer_new( PurpleXfer *xfer ) } else { + /* struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); px->ft = next_ft; @@ -135,54 +98,43 @@ static void prplcb_xfer_new( PurpleXfer *xfer ) purple_xfer_set_size( xfer, px->ft->file_size ); next_ft = NULL; + */ } } -static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) -{ - fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent ); -} - -static void prplcb_xfer_dbg( PurpleXfer *xfer ) -{ - fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); -} - -static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size ) +static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) { - struct prpl_xfer_data *px = xfer->ui_data; - gboolean st; - - fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len ); + PurpleXfer *xfer = data; + struct im_connection *ic = purple_ic_by_pa( xfer->account ); + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + PurpleBuddy *buddy; + const char *who; - b_event_remove( px->ready_timer ); - px->ready_timer = 0; + buddy = purple_find_buddy( xfer->account, xfer->who ); + who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; - st = px->ft->write( px->ft, (char*) buffer, size ); + /* TODO(wilmer): After spreading some more const goodness in BitlBee, + remove the evil cast below. */ + px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); + px->ft->data = px; + px->xfer = data; + px->xfer->ui_data = px; - if( st && xfer->bytes_remaining == size ) - imcb_file_finished( px->ft ); + px->ft->accept = prpl_xfer_accept; + px->ft->canceled = prpl_xfer_canceled; + px->ft->write_request = prpl_xfer_write_request; - return st ? size : 0; + return FALSE; } -gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size ) +static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) { - struct prpl_xfer_data *px = xfer->ui_data; - - fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len ); + fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent ); +} - if( px->buf ) - { - *buffer = px->buf; - px->buf = NULL; - - px->ft->write_request( px->ft ); - - return px->buf_len; - } - - return 0; +static void prplcb_xfer_dbg( PurpleXfer *xfer ) +{ + fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); } PurpleXferUiOps bee_xfer_uiops = @@ -193,8 +145,8 @@ PurpleXferUiOps bee_xfer_uiops = prplcb_xfer_progress, prplcb_xfer_dbg, prplcb_xfer_dbg, - prplcb_xfer_write, - prplcb_xfer_read, + NULL, + NULL, prplcb_xfer_dbg, }; @@ -214,21 +166,4 @@ void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, cha px = ft->data; imcb_file_recv_start( ft ); - - px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px ); -} - -static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ) -{ - struct prpl_xfer_data *px = data; - - if( px->ft->status & FT_STATUS_TRANSFERRING ) - { - fprintf( stderr, "The ft, it is ready...\n" ); - px->ft->write_request( px->ft ); - - return FALSE; - } - - return TRUE; } -- cgit v1.2.3 From 8822d23385bf7c35d67eaff1d0ce81470ba73f4f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 18 May 2010 00:23:20 +0100 Subject: This receives files but is very fragile if anything unusual happens (like a cancellation/timeout/etc). --- protocols/purple/ft.c | 117 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 15 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c index 4b5a3f49..57d45beb 100644 --- a/protocols/purple/ft.c +++ b/protocols/purple/ft.c @@ -37,24 +37,74 @@ struct prpl_xfer_data { PurpleXfer *xfer; file_transfer_t *ft; - gint ready_timer; - char *buf; - int buf_len; + int fd; + char *fn; + gboolean ui_wants_data; }; static file_transfer_t *next_ft; struct im_connection *purple_ic_by_pa( PurpleAccount *pa ); -static gboolean prpl_xfer_write_request( struct file_transfer *ft ) +gboolean try_write_to_ui( gpointer data, gint fd, b_input_condition cond ) { + struct file_transfer *ft = data; + struct prpl_xfer_data *px = ft->data; + struct stat fs; + off_t tx_bytes; + + fprintf( stderr, "write_to_ui\n" ); + + /* If we don't have the file opened yet, there's no data so wait. */ + if( px->fd < 0 || !px->ui_wants_data ) + return FALSE; + + tx_bytes = lseek( px->fd, 0, SEEK_CUR ); + fstat( px->fd, &fs ); + + fprintf( stderr, "write_to_ui %zd %zd %zd\n", fs.st_size, tx_bytes, px->xfer->size ); + + if( fs.st_size > tx_bytes ) + { + char buf[1024]; + size_t n = MIN( fs.st_size - tx_bytes, sizeof( buf ) ); + + if( read( px->fd, buf, n ) == n && ft->write( ft, buf, n ) ) + { + fprintf( stderr, "Wrote %zd bytes\n", n ); + px->ui_wants_data = FALSE; + } + else + { + purple_xfer_cancel_local( px->xfer ); + imcb_file_canceled( ft, "Read error" ); + } + } + + if( lseek( px->fd, 0, SEEK_CUR ) == px->xfer->size ) + { + purple_xfer_end( px->xfer ); + imcb_file_finished( ft ); + } + return FALSE; } -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +/* UI calls this when its buffer is empty and wants more data to send to the user. */ +static gboolean prpl_xfer_write_request( struct file_transfer *ft ) { struct prpl_xfer_data *px = ft->data; + fprintf( stderr, "wrq\n" ); + + px->ui_wants_data = TRUE; + try_write_to_ui( ft, 0, 0 ); + + return FALSE; +} + +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +{ return FALSE; } @@ -77,8 +127,14 @@ static void prplcb_xfer_new( PurpleXfer *xfer ) { if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) { - /* This should suppress the stupid file dialog. */ - purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + + xfer->ui_data = px; + px->xfer = xfer; + px->fn = mktemp( g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ) ); + px->fd = -1; + + purple_xfer_set_local_filename( xfer, px->fn ); /* Sadly the xfer struct is still empty ATM so come back after the caller is done. */ @@ -89,6 +145,7 @@ static void prplcb_xfer_new( PurpleXfer *xfer ) /* struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + px->fd = -1; px->ft = next_ft; px->ft->data = px; px->xfer = xfer; @@ -106,7 +163,7 @@ static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_conditi { PurpleXfer *xfer = data; struct im_connection *ic = purple_ic_by_pa( xfer->account ); - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + struct prpl_xfer_data *px = xfer->ui_data; PurpleBuddy *buddy; const char *who; @@ -117,8 +174,6 @@ static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_conditi remove the evil cast below. */ px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); px->ft->data = px; - px->xfer = data; - px->xfer->ui_data = px; px->ft->accept = prpl_xfer_accept; px->ft->canceled = prpl_xfer_canceled; @@ -127,9 +182,43 @@ static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_conditi return FALSE; } +static void prplcb_xfer_destroy( PurpleXfer *xfer ) +{ + struct prpl_xfer_data *px = xfer->ui_data; + + g_free( px->fn ); + if( px->fd >= 0 ) + close( px->fd ); + g_free( px ); +} + static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) { - fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent ); + struct prpl_xfer_data *px = xfer->ui_data; + + fprintf( stderr, "prplcb_xfer_progress 0x%p %f\n", xfer, percent ); + + if( px->fd == -1 && percent > 0 ) + { + /* Weeeeeeeee, we're getting data! That means the file exists + by now so open it and start sending to the UI. */ + px->fd = open( px->fn, O_RDONLY ); + + /* Unlink it now, because we don't need it after this. */ + //unlink( px->fn ); + } + + if( percent < 1 ) + try_write_to_ui( px->ft, 0, 0 ); + else + b_timeout_add( 0, try_write_to_ui, px->ft ); +} + +static void prplcb_xfer_cancel_remote( PurpleXfer *xfer ) +{ + struct prpl_xfer_data *px = xfer->ui_data; + + imcb_file_canceled( px->ft, "Canceled by remote end" ); } static void prplcb_xfer_dbg( PurpleXfer *xfer ) @@ -140,18 +229,16 @@ static void prplcb_xfer_dbg( PurpleXfer *xfer ) PurpleXferUiOps bee_xfer_uiops = { prplcb_xfer_new, - prplcb_xfer_dbg, + prplcb_xfer_destroy, prplcb_xfer_dbg, prplcb_xfer_progress, prplcb_xfer_dbg, - prplcb_xfer_dbg, + prplcb_xfer_cancel_remote, NULL, NULL, prplcb_xfer_dbg, }; -static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ); - void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) { PurpleAccount *pa = ic->proto_data; -- cgit v1.2.3 From 5d1b3a9529f7aadab62026be0eb9f4ca0f6311ce Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 18 May 2010 00:38:39 +0100 Subject: purple_conv_chat_invite_user() is libpurple >= 2.6.0, so use serv_chat_invite() instead. --- protocols/purple/purple.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index b01fb991..eb3a4eb5 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -448,7 +448,10 @@ void purple_chat_invite( struct groupchat *gc, char *who, char *message ) PurpleConversation *pc = gc->data; PurpleConvChat *pcc = PURPLE_CONV_CHAT( pc ); - purple_conv_chat_invite_user( pcc, who, message && *message ? message : "Please join my chat", FALSE ); + serv_chat_invite( purple_account_get_connection( gc->ic->proto_data ), + purple_conv_chat_get_id( pcc ), + message && *message ? message : "Please join my chat", + who ); } void purple_chat_leave( struct groupchat *gc, char *who ) -- cgit v1.2.3 From c96c72f16ea48ca769400ff91bd2eb434da19f6e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 18 May 2010 01:08:17 +0100 Subject: Little cleanup. Less compiler warnings, and removing tempfile at the beginning of the download already to make sure it doesn't stick around. --- protocols/purple/ft.c | 158 ++++++++++++++++++++++++---------------------- protocols/purple/purple.c | 7 +- 2 files changed, 85 insertions(+), 80 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c index 57d45beb..8cfa60dd 100644 --- a/protocols/purple/ft.c +++ b/protocols/purple/ft.c @@ -45,69 +45,11 @@ struct prpl_xfer_data static file_transfer_t *next_ft; struct im_connection *purple_ic_by_pa( PurpleAccount *pa ); +static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ); +static gboolean prpl_xfer_write_request( struct file_transfer *ft ); -gboolean try_write_to_ui( gpointer data, gint fd, b_input_condition cond ) -{ - struct file_transfer *ft = data; - struct prpl_xfer_data *px = ft->data; - struct stat fs; - off_t tx_bytes; - - fprintf( stderr, "write_to_ui\n" ); - - /* If we don't have the file opened yet, there's no data so wait. */ - if( px->fd < 0 || !px->ui_wants_data ) - return FALSE; - - tx_bytes = lseek( px->fd, 0, SEEK_CUR ); - fstat( px->fd, &fs ); - - fprintf( stderr, "write_to_ui %zd %zd %zd\n", fs.st_size, tx_bytes, px->xfer->size ); - - if( fs.st_size > tx_bytes ) - { - char buf[1024]; - size_t n = MIN( fs.st_size - tx_bytes, sizeof( buf ) ); - - if( read( px->fd, buf, n ) == n && ft->write( ft, buf, n ) ) - { - fprintf( stderr, "Wrote %zd bytes\n", n ); - px->ui_wants_data = FALSE; - } - else - { - purple_xfer_cancel_local( px->xfer ); - imcb_file_canceled( ft, "Read error" ); - } - } - - if( lseek( px->fd, 0, SEEK_CUR ) == px->xfer->size ) - { - purple_xfer_end( px->xfer ); - imcb_file_finished( ft ); - } - - return FALSE; -} - -/* UI calls this when its buffer is empty and wants more data to send to the user. */ -static gboolean prpl_xfer_write_request( struct file_transfer *ft ) -{ - struct prpl_xfer_data *px = ft->data; - - fprintf( stderr, "wrq\n" ); - - px->ui_wants_data = TRUE; - try_write_to_ui( ft, 0, 0 ); - - return FALSE; -} - -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) -{ - return FALSE; -} +/* Receiving files (IM->UI): */ static void prpl_xfer_accept( struct file_transfer *ft ) { struct prpl_xfer_data *px = ft->data; @@ -121,8 +63,6 @@ static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) purple_xfer_request_denied( px->xfer ); } -static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ); - static void prplcb_xfer_new( PurpleXfer *xfer ) { if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) @@ -182,6 +122,58 @@ static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_conditi return FALSE; } +gboolean try_write_to_ui( gpointer data, gint fd, b_input_condition cond ) +{ + struct file_transfer *ft = data; + struct prpl_xfer_data *px = ft->data; + struct stat fs; + off_t tx_bytes; + + /* If we don't have the file opened yet, there's no data so wait. */ + if( px->fd < 0 || !px->ui_wants_data ) + return FALSE; + + tx_bytes = lseek( px->fd, 0, SEEK_CUR ); + fstat( px->fd, &fs ); + + if( fs.st_size > tx_bytes ) + { + char buf[1024]; + size_t n = MIN( fs.st_size - tx_bytes, sizeof( buf ) ); + + if( read( px->fd, buf, n ) == n && ft->write( ft, buf, n ) ) + { + px->ui_wants_data = FALSE; + } + else + { + purple_xfer_cancel_local( px->xfer ); + imcb_file_canceled( ft, "Read error" ); + } + } + + if( lseek( px->fd, 0, SEEK_CUR ) == px->xfer->size ) + { + purple_xfer_end( px->xfer ); + imcb_file_finished( ft ); + } + + return FALSE; +} + +/* UI calls this when its buffer is empty and wants more data to send to the user. */ +static gboolean prpl_xfer_write_request( struct file_transfer *ft ) +{ + struct prpl_xfer_data *px = ft->data; + + px->ui_wants_data = TRUE; + try_write_to_ui( ft, 0, 0 ); + + return FALSE; +} + + +/* Generic (IM<>UI): */ static void prplcb_xfer_destroy( PurpleXfer *xfer ) { struct prpl_xfer_data *px = xfer->ui_data; @@ -196,8 +188,6 @@ static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) { struct prpl_xfer_data *px = xfer->ui_data; - fprintf( stderr, "prplcb_xfer_progress 0x%p %f\n", xfer, percent ); - if( px->fd == -1 && percent > 0 ) { /* Weeeeeeeee, we're getting data! That means the file exists @@ -205,12 +195,16 @@ static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) px->fd = open( px->fn, O_RDONLY ); /* Unlink it now, because we don't need it after this. */ - //unlink( px->fn ); + unlink( px->fn ); } if( percent < 1 ) try_write_to_ui( px->ft, 0, 0 ); else + /* Another nice problem: If we have the whole file, it only + gets closed when we return. Problem: There may still be + stuff buffered and not written, we'll only see it after + the caller close()s the file. So poll the file after that. */ b_timeout_add( 0, try_write_to_ui, px->ft ); } @@ -226,18 +220,12 @@ static void prplcb_xfer_dbg( PurpleXfer *xfer ) fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); } -PurpleXferUiOps bee_xfer_uiops = + +/* Sending files (UI->IM): */ +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) { - prplcb_xfer_new, - prplcb_xfer_destroy, - prplcb_xfer_dbg, - prplcb_xfer_progress, - prplcb_xfer_dbg, - prplcb_xfer_cancel_remote, - NULL, - NULL, - prplcb_xfer_dbg, -}; + return FALSE; +} void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) { @@ -254,3 +242,19 @@ void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, cha px = ft->data; imcb_file_recv_start( ft ); } + + + + +PurpleXferUiOps bee_xfer_uiops = +{ + prplcb_xfer_new, + prplcb_xfer_destroy, + prplcb_xfer_dbg, + prplcb_xfer_progress, + prplcb_xfer_dbg, + prplcb_xfer_cancel_remote, + NULL, + NULL, + prplcb_xfer_dbg, +}; diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index eb3a4eb5..2507bfc2 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -141,10 +141,11 @@ static void purple_init( account_t *acc ) { PurpleKeyValuePair *kv = io->data; opts = g_slist_append( opts, kv->value ); + /* TODO: kv->value is not a char*, WTF? */ if( strcmp( kv->value, kv->key ) != 0 ) - g_string_append_printf( help, "%s (%s), ", kv->value, kv->key ); + g_string_append_printf( help, "%s (%s), ", (char*) kv->value, kv->key ); else - g_string_append_printf( help, "%s, ", kv->value ); + g_string_append_printf( help, "%s, ", (char*) kv->value ); } g_string_truncate( help, help->len - 2 ); eval = set_eval_list; @@ -454,7 +455,7 @@ void purple_chat_invite( struct groupchat *gc, char *who, char *message ) who ); } -void purple_chat_leave( struct groupchat *gc, char *who ) +void purple_chat_leave( struct groupchat *gc ) { PurpleConversation *pc = gc->data; -- cgit v1.2.3 From 31fc06fbb48b6217186ca441eb9b95add5f783ce Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 18 May 2010 01:42:02 +0100 Subject: Suppress auto-reconnect when required (auth errors and concurrent logins probably, not sure what sets the wants_to_die flag). --- protocols/purple/purple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 2507bfc2..fee93b27 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -497,7 +497,7 @@ static void prplcb_conn_disconnected( PurpleConnection *gc ) if( ic != NULL ) { - imc_logout( ic, TRUE ); + imc_logout( ic, !gc->wants_to_die ); } } -- cgit v1.2.3 From e7dc02a89d846d27b63719a5093c2e2a295fc232 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 19 May 2010 01:57:58 +0100 Subject: Similar hacky code to send files. This indirect sending stuff sucks badly for numerous reasons. Maybe libpurple 2.7.0 is less crappy and will eventually allow (working) direct ft's again. This somewhat works, but filename info is lost with some protocols. --- protocols/purple/ft.c | 113 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 20 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c index 8cfa60dd..ab637a94 100644 --- a/protocols/purple/ft.c +++ b/protocols/purple/ft.c @@ -37,8 +37,9 @@ struct prpl_xfer_data { PurpleXfer *xfer; file_transfer_t *ft; + struct im_connection *ic; int fd; - char *fn; + char *fn, *orig_fn, *handle; gboolean ui_wants_data; }; @@ -82,20 +83,16 @@ static void prplcb_xfer_new( PurpleXfer *xfer ) } else { - /* - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + struct file_transfer *ft = next_ft; + struct prpl_xfer_data *px = ft->data; - px->fd = -1; - px->ft = next_ft; - px->ft->data = px; + xfer->ui_data = px; px->xfer = xfer; - px->xfer->ui_data = px; - purple_xfer_set_filename( xfer, px->ft->file_name ); - purple_xfer_set_size( xfer, px->ft->file_size ); + purple_xfer_set_filename( xfer, px->orig_fn ); + purple_xfer_set_local_filename( xfer, px->fn ); next_ft = NULL; - */ } } @@ -179,6 +176,8 @@ static void prplcb_xfer_destroy( PurpleXfer *xfer ) struct prpl_xfer_data *px = xfer->ui_data; g_free( px->fn ); + g_free( px->orig_fn ); + g_free( px->handle ); if( px->fd >= 0 ) close( px->fd ); g_free( px ); @@ -188,6 +187,20 @@ static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) { struct prpl_xfer_data *px = xfer->ui_data; + if( px == NULL ) + return; + + if( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) + { + if( *px->fn ) + { + //unlink( px->fn ); + *px->fn = '\0'; + } + + return; + } + if( px->fd == -1 && percent > 0 ) { /* Weeeeeeeee, we're getting data! That means the file exists @@ -215,6 +228,16 @@ static void prplcb_xfer_cancel_remote( PurpleXfer *xfer ) imcb_file_canceled( px->ft, "Canceled by remote end" ); } +static void prplcb_xfer_add( PurpleXfer *xfer ) +{ + if( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) + { + struct prpl_xfer_data *px = xfer->ui_data; + + purple_xfer_set_filename( xfer, px->orig_fn ); + } +} + static void prplcb_xfer_dbg( PurpleXfer *xfer ) { fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); @@ -222,27 +245,77 @@ static void prplcb_xfer_dbg( PurpleXfer *xfer ) /* Sending files (UI->IM): */ -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ); +static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond ); + +void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) { - return FALSE; + struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + + ft->data = px; + px->ft = ft; + px->fn = g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ); + px->fd = mkstemp( px->fn ); + + px->ic = ic; + px->handle = g_strdup( handle ); + px->orig_fn = g_strdup( ft->file_name ); + + 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 ); } -void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) +static void purple_transfer_forward( struct file_transfer *ft ) { - PurpleAccount *pa = ic->proto_data; - struct prpl_xfer_data *px; + struct prpl_xfer_data *px = ft->data; + PurpleAccount *pa = px->ic->proto_data; /* xfer_new() will pick up this variable. It's a hack but we're not multi-threaded anyway. */ next_ft = ft; - serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name ); + serv_send_file( purple_account_get_connection( pa ), px->handle, px->fn ); +} + +static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond ) +{ + file_transfer_t *ft = data; + + if( ft->write == NULL ) + { + ft->write = prpl_xfer_write; + imcb_file_recv_start( ft ); + } - ft->write = prpl_xfer_write; + ft->write_request( ft ); - px = ft->data; - imcb_file_recv_start( ft ); + return FALSE; } +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +{ + struct prpl_xfer_data *px = ft->data; + + if( write( px->fd, buffer, len ) != len ) + { + imcb_file_canceled( ft, "Error while writing temporary file" ); + return FALSE; + } + + if( lseek( px->fd, 0, SEEK_CUR ) >= ft->file_size ) + { + close( px->fd ); + px->fd = -1; + + purple_transfer_forward( ft ); + imcb_file_finished( ft ); + px->ft = NULL; + } + else + b_timeout_add( 0, purple_transfer_request_cb, ft ); + + return TRUE; +} @@ -250,7 +323,7 @@ PurpleXferUiOps bee_xfer_uiops = { prplcb_xfer_new, prplcb_xfer_destroy, - prplcb_xfer_dbg, + prplcb_xfer_add, prplcb_xfer_progress, prplcb_xfer_dbg, prplcb_xfer_cancel_remote, -- cgit v1.2.3 From 75c3ff711698ea069f33ffc460c2e7aec650e875 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 21 May 2010 01:09:29 +0100 Subject: Fixed sending with proper filenames by creating a temporary directory with the file in it; protocol modules are mostly hardcoded to use the filename from the filesystem with no way to override this. Also improved robustness a little bit. --- protocols/purple/ft.c | 64 +++++++++++++++++++++++++++++++---------------- protocols/purple/purple.c | 2 +- 2 files changed, 43 insertions(+), 23 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c index ab637a94..e3a89524 100644 --- a/protocols/purple/ft.c +++ b/protocols/purple/ft.c @@ -39,7 +39,7 @@ struct prpl_xfer_data file_transfer_t *ft; struct im_connection *ic; int fd; - char *fn, *orig_fn, *handle; + char *fn, *handle; gboolean ui_wants_data; }; @@ -89,9 +89,6 @@ static void prplcb_xfer_new( PurpleXfer *xfer ) xfer->ui_data = px; px->xfer = xfer; - purple_xfer_set_filename( xfer, px->orig_fn ); - purple_xfer_set_local_filename( xfer, px->fn ); - next_ft = NULL; } } @@ -151,7 +148,7 @@ gboolean try_write_to_ui( gpointer data, gint fd, b_input_condition cond ) if( lseek( px->fd, 0, SEEK_CUR ) == px->xfer->size ) { - purple_xfer_end( px->xfer ); + /*purple_xfer_end( px->xfer );*/ imcb_file_finished( ft ); } @@ -176,7 +173,6 @@ static void prplcb_xfer_destroy( PurpleXfer *xfer ) struct prpl_xfer_data *px = xfer->ui_data; g_free( px->fn ); - g_free( px->orig_fn ); g_free( px->handle ); if( px->fd >= 0 ) close( px->fd ); @@ -194,7 +190,14 @@ static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) { if( *px->fn ) { - //unlink( px->fn ); + char *slash; + + unlink( px->fn ); + if( ( slash = strrchr( px->fn, '/' ) ) ) + { + *slash = '\0'; + rmdir( px->fn ); + } *px->fn = '\0'; } @@ -225,17 +228,11 @@ static void prplcb_xfer_cancel_remote( PurpleXfer *xfer ) { struct prpl_xfer_data *px = xfer->ui_data; - imcb_file_canceled( px->ft, "Canceled by remote end" ); -} - -static void prplcb_xfer_add( PurpleXfer *xfer ) -{ - if( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) - { - struct prpl_xfer_data *px = xfer->ui_data; - - purple_xfer_set_filename( xfer, px->orig_fn ); - } + if( px->ft ) + imcb_file_canceled( px->ft, "Canceled by remote end" ); + else + /* px->ft == NULL for sends, because of the two stages. :-/ */ + imcb_error( px->ic, "File transfer cancelled by remote end" ); } static void prplcb_xfer_dbg( PurpleXfer *xfer ) @@ -251,15 +248,38 @@ static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_cond 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 ); + char *dir, *basename; ft->data = px; px->ft = ft; - px->fn = g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ); - px->fd = mkstemp( px->fn ); + + dir = g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ); + if( !mkdtemp( dir ) ) + { + imcb_error( ic, "Could not create temporary file for file transfer" ); + g_free( px ); + g_free( dir ); + return; + } + + if( ( basename = strrchr( ft->file_name, '/' ) ) ) + basename++; + else + basename = ft->file_name; + px->fn = g_strdup_printf( "%s/%s", dir, basename ); + px->fd = open( px->fn, O_WRONLY | O_CREAT, 0600 ); + g_free( dir ); + + if( px->fd < 0 ) + { + imcb_error( ic, "Could not create temporary file for file transfer" ); + g_free( px ); + g_free( px->fn ); + return; + } px->ic = ic; px->handle = g_strdup( handle ); - px->orig_fn = g_strdup( ft->file_name ); imcb_log( ic, "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait..." ); @@ -323,7 +343,7 @@ PurpleXferUiOps bee_xfer_uiops = { prplcb_xfer_new, prplcb_xfer_destroy, - prplcb_xfer_add, + NULL, /* prplcb_xfer_add, */ prplcb_xfer_progress, prplcb_xfer_dbg, prplcb_xfer_cancel_remote, diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index fee93b27..799a8a80 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -840,7 +840,7 @@ static void purple_ui_init() purple_request_set_ui_ops( &bee_request_uiops ); purple_notify_set_ui_ops( &bee_notify_uiops ); purple_xfers_set_ui_ops( &bee_xfer_uiops ); - //purple_debug_set_ui_ops( &bee_debug_uiops ); + purple_debug_set_ui_ops( &bee_debug_uiops ); } void purple_initmodule() -- cgit v1.2.3 From 2c5fabcf9066752eed45ad0334fca232a7123629 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 22 May 2010 00:26:21 +0100 Subject: Sigh. Enable debugging only if the BITLBEE_DEBUG variable is set. --- protocols/purple/purple.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 799a8a80..f11cefcb 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -840,7 +840,9 @@ static void purple_ui_init() purple_request_set_ui_ops( &bee_request_uiops ); purple_notify_set_ui_ops( &bee_notify_uiops ); purple_xfers_set_ui_ops( &bee_xfer_uiops ); - purple_debug_set_ui_ops( &bee_debug_uiops ); + + if( getenv( "BITLBEE_DEBUG" ) ) + purple_debug_set_ui_ops( &bee_debug_uiops ); } void purple_initmodule() -- cgit v1.2.3 From e77c2647c3f4d8d6518239f070f3989444003a08 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 22 May 2010 01:58:59 +0100 Subject: Added support for the info command. --- protocols/purple/purple.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index f11cefcb..1d17b012 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -358,6 +358,11 @@ static void purple_remove_buddy( struct im_connection *ic, char *who, char *grou } } +static void purple_get_info( struct im_connection *ic, char *who ) +{ + serv_get_info( purple_account_get_connection( ic->proto_data ), who ); +} + static void purple_keepalive( struct im_connection *ic ) { } @@ -824,10 +829,66 @@ static void *prplcb_notify_email( PurpleConnection *gc, const char *subject, con return NULL; } +static void *prplcb_notify_userinfo( PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info ) +{ + struct im_connection *ic = purple_ic_by_gc( gc ); + GString *info = g_string_new( "" ); + GList *l = purple_notify_user_info_get_entries( user_info ); + char *key; + const char *value; + int n; + + while( l ) + { + PurpleNotifyUserInfoEntry *e = l->data; + + switch( purple_notify_user_info_entry_get_type( e ) ) + { + case PURPLE_NOTIFY_USER_INFO_ENTRY_PAIR: + case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER: + key = g_strdup( purple_notify_user_info_entry_get_label( e ) ); + value = purple_notify_user_info_entry_get_value( e ); + + if( key ) + { + strip_html( key ); + g_string_append_printf( info, "%s: ", key ); + + if( value ) + { + n = strlen( value ) - 1; + while( isspace( value[n] ) ) + n --; + g_string_append_len( info, value, n + 1 ); + } + g_string_append_c( info, '\n' ); + g_free( key ); + } + + break; + case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK: + g_string_append( info, "------------------------\n" ); + break; + } + + l = l->next; + } + + imcb_log( ic, "User %s info:\n%s", who, info->str ); + g_string_free( info, TRUE ); + + return NULL; +} + static PurpleNotifyUiOps bee_notify_uiops = { NULL, prplcb_notify_email, + NULL, + NULL, + NULL, + NULL, + prplcb_notify_userinfo, }; extern PurpleXferUiOps bee_xfer_uiops; @@ -885,6 +946,7 @@ void purple_initmodule() funcs.set_away = purple_set_away; funcs.add_buddy = purple_add_buddy; funcs.remove_buddy = purple_remove_buddy; + funcs.get_info = purple_get_info; funcs.keepalive = purple_keepalive; funcs.send_typing = purple_send_typing; funcs.handle_cmp = g_strcasecmp; -- cgit v1.2.3 From dca8effbf732557e28a6a03d2fcf785d69a5a1bd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 22 May 2010 02:05:58 +0100 Subject: Return ui_info so jabber:iq:version responses will not say just libpurple. --- protocols/purple/purple.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 1d17b012..7b020cf7 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -471,12 +471,27 @@ void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, cha static void purple_ui_init(); +GHashTable *prplcb_ui_info() +{ + static GHashTable *ret; + + if( ret == NULL ) + { + ret = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert( ret, "name", "BitlBee" ); + g_hash_table_insert( ret, "version", BITLBEE_VERSION ); + } + + return ret; +} + static PurpleCoreUiOps bee_core_uiops = { NULL, NULL, purple_ui_init, NULL, + prplcb_ui_info, }; static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count ) -- cgit v1.2.3 From 05a8932daa3e8f6d3dd4c5177fa04d1f17254000 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 22 May 2010 13:21:27 +0100 Subject: Enable changing and viewing of block/allow lists. --- protocols/purple/purple.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 7b020cf7..c9588d7a 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -358,6 +358,34 @@ static void purple_remove_buddy( struct im_connection *ic, char *who, char *grou } } +static void purple_add_permit( struct im_connection *ic, char *who ) +{ + PurpleAccount *pa = ic->proto_data; + + purple_privacy_permit_add( pa, who, FALSE ); +} + +static void purple_add_deny( struct im_connection *ic, char *who ) +{ + PurpleAccount *pa = ic->proto_data; + + purple_privacy_deny_add( pa, who, FALSE ); +} + +static void purple_rem_permit( struct im_connection *ic, char *who ) +{ + PurpleAccount *pa = ic->proto_data; + + purple_privacy_permit_remove( pa, who, FALSE ); +} + +static void purple_rem_deny( struct im_connection *ic, char *who ) +{ + PurpleAccount *pa = ic->proto_data; + + purple_privacy_deny_remove( pa, who, FALSE ); +} + static void purple_get_info( struct im_connection *ic, char *who ) { serv_get_info( purple_account_get_connection( ic->proto_data ), who ); @@ -800,6 +828,48 @@ static PurpleRequestUiOps bee_request_uiops = NULL, }; +static void prplcb_privacy_permit_added( PurpleAccount *account, const char *name ) +{ + struct im_connection *ic = purple_ic_by_pa( account ); + + if( !g_slist_find_custom( ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) + ic->permit = g_slist_prepend( ic->permit, g_strdup( name ) ); +} + +static void prplcb_privacy_permit_removed( PurpleAccount *account, const char *name ) +{ + struct im_connection *ic = purple_ic_by_pa( account ); + void *n; + + n = g_slist_find_custom( ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp ); + ic->permit = g_slist_remove( ic->permit, n ); +} + +static void prplcb_privacy_deny_added( PurpleAccount *account, const char *name ) +{ + struct im_connection *ic = purple_ic_by_pa( account ); + + if( !g_slist_find_custom( ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) + ic->deny = g_slist_prepend( ic->deny, g_strdup( name ) ); +} + +static void prplcb_privacy_deny_removed( PurpleAccount *account, const char *name ) +{ + struct im_connection *ic = purple_ic_by_pa( account ); + void *n; + + n = g_slist_find_custom( ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp ); + ic->deny = g_slist_remove( ic->deny, n ); +} + +static PurplePrivacyUiOps bee_privacy_uiops = +{ + prplcb_privacy_permit_added, + prplcb_privacy_permit_removed, + prplcb_privacy_deny_added, + prplcb_privacy_deny_removed, +}; + static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s ) { fprintf( stderr, "DEBUG %s: %s", category, arg_s ); @@ -916,6 +986,7 @@ static void purple_ui_init() purple_request_set_ui_ops( &bee_request_uiops ); purple_notify_set_ui_ops( &bee_notify_uiops ); purple_xfers_set_ui_ops( &bee_xfer_uiops ); + purple_privacy_set_ui_ops( &bee_privacy_uiops ); if( getenv( "BITLBEE_DEBUG" ) ) purple_debug_set_ui_ops( &bee_debug_uiops ); @@ -961,6 +1032,10 @@ void purple_initmodule() funcs.set_away = purple_set_away; funcs.add_buddy = purple_add_buddy; funcs.remove_buddy = purple_remove_buddy; + funcs.add_permit = purple_add_permit; + funcs.add_deny = purple_add_deny; + funcs.rem_permit = purple_rem_permit; + funcs.rem_deny = purple_rem_deny; funcs.get_info = purple_get_info; funcs.keepalive = purple_keepalive; funcs.send_typing = purple_send_typing; -- cgit v1.2.3 From c3caa46bc5c5ac0a372a13c5fe0de79845a7dabf Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 22 May 2010 14:46:25 +0100 Subject: Support for named groupchats, although not very solid. --- protocols/purple/purple.c | 52 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index c9588d7a..b91b7aca 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -495,6 +495,44 @@ void purple_chat_leave( struct groupchat *gc ) purple_conversation_destroy( pc ); } +struct groupchat *purple_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password ) +{ + PurpleAccount *pa = ic->proto_data; + PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id ); + PurplePluginProtocolInfo *pi = prpl->info->extra_info; + GHashTable *chat_hash; + PurpleConversation *conv; + GList *info, *l; + + if( !pi->chat_info || !pi->chat_info_defaults || + !( info = pi->chat_info( purple_account_get_connection( pa ) ) ) ) + { + imcb_error( ic, "Joining chatrooms not supported by this protocol" ); + return NULL; + } + + if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_CHAT, room, pa ) ) ) + purple_conversation_destroy( conv ); + + chat_hash = pi->chat_info_defaults( purple_account_get_connection( pa ), room ); + + for( l = info; l; l = l->next ) + { + struct proto_chat_entry *pce = l->data; + + if( strcmp( pce->identifier, "handle" ) == 0 ) + g_hash_table_replace( chat_hash, "handle", g_strdup( nick ) ); + else if( strcmp( pce->identifier, "password" ) == 0 ) + g_hash_table_replace( chat_hash, "password", g_strdup( password ) ); + else if( strcmp( pce->identifier, "passwd" ) == 0 ) + g_hash_table_replace( chat_hash, "passwd", g_strdup( password ) ); + } + + serv_join_chat( purple_account_get_connection( pa ), chat_hash ); + + return NULL; +} + void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ); static void purple_ui_init(); @@ -661,6 +699,11 @@ void prplcb_conv_new( PurpleConversation *conv ) gc = imcb_chat_new( ic, conv->name ); conv->ui_data = gc; gc->data = conv; + + /* libpurple brokenness: Whatever. Show that we join right away, + there's no clear "This is you!" signaling in _add_users so + don't even try. */ + imcb_chat_add_buddy( gc, gc->ic->acc->user ); } } @@ -676,14 +719,6 @@ void prplcb_conv_add_users( PurpleConversation *conv, GList *cbuddies, gboolean struct groupchat *gc = conv->ui_data; GList *b; - if( !gc->joined && strcmp( conv->account->protocol_id, "prpl-msn" ) == 0 ) - { - /* Work around the broken MSN module which fucks up the user's - handle completely when informing him/her that he just - successfully joined the room s/he just created (v2.6.6). */ - imcb_chat_add_buddy( gc, gc->ic->acc->user ); - } - for( b = cbuddies; b; b = b->next ) { PurpleConvChatBuddy *pcb = b->data; @@ -1045,6 +1080,7 @@ void purple_initmodule() funcs.chat_with = purple_chat_with; funcs.chat_invite = purple_chat_invite; funcs.chat_leave = purple_chat_leave; + funcs.chat_join = purple_chat_join; funcs.transfer_request = purple_transfer_request; help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); -- cgit v1.2.3 From f85e9d6846d7b4ec0109180e62ae8677e2421fa3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 24 May 2010 22:24:53 +0100 Subject: Read display names. Setting them is going to be an awesome hack. --- protocols/purple/purple.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index b91b7aca..98cd2241 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -36,6 +36,8 @@ GSList *purple_connections; libpurple in daemon mode anyway. */ static irc_t *local_irc; +static char *set_eval_display_name( set_t *set, char *value ); + struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) { GSList *i; @@ -172,6 +174,9 @@ static void purple_init( account_t *acc ) help_add_mem( &global.help, help_title, help->str ); g_string_free( help, TRUE ); + s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); + s->flags |= ACC_SET_ONLINE_ONLY; + if( pi->options & OPT_PROTO_MAIL_CHECK ) { s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); @@ -337,6 +342,14 @@ static void purple_set_away( struct im_connection *ic, char *state_txt, char *me g_list_free( args ); } +static char *set_eval_display_name( set_t *set, char *value ) +{ + account_t *acc = set->data; + struct im_connection *ic = acc->ic; + + return NULL; +} + static void purple_add_buddy( struct im_connection *ic, char *who, char *group ) { PurpleBuddy *pb; @@ -570,9 +583,18 @@ static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t static void prplcb_conn_connected( PurpleConnection *gc ) { struct im_connection *ic = purple_ic_by_gc( gc ); + const char *dn; + set_t *s; imcb_connected( ic ); + if( ( dn = purple_connection_get_display_name( gc ) ) && + ( s = set_find( &ic->acc->set, "display_name" ) ) ) + { + g_free( s->value ); + s->value = g_strdup( dn ); + } + if( gc->flags & PURPLE_CONNECTION_HTML ) ic->flags |= OPT_DOES_HTML; } -- cgit v1.2.3 From d25ebea73aef7d6b2bbc17212af5109383277e6e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 25 May 2010 23:04:55 +0100 Subject: GAIM_INPUT_* were renamed, at last. --- protocols/jabber/s5bytestream.c | 14 +++++++------- protocols/msn/invitation.c | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'protocols') diff --git a/protocols/jabber/s5bytestream.c b/protocols/jabber/s5bytestream.c index 58a6c2e4..14611a6f 100644 --- a/protocols/jabber/s5bytestream.c +++ b/protocols/jabber/s5bytestream.c @@ -405,7 +405,7 @@ gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition con bt->phase = BS_PHASE_CONNECTED; - bt->tf->watch_out = b_input_add( fd, GAIM_INPUT_WRITE, jabber_bs_recv_handshake, bt ); + bt->tf->watch_out = b_input_add( fd, B_EV_IO_WRITE, jabber_bs_recv_handshake, bt ); /* since it takes forever(3mins?) till connect() fails on itself we schedule a timeout */ bt->connect_timeout = b_timeout_add( JABBER_BS_CONTIMEOUT * 1000, jabber_bs_connect_timeout, bt ); @@ -432,7 +432,7 @@ gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition con bt->phase = BS_PHASE_REQUEST; - bt->tf->watch_in = b_input_add( fd, GAIM_INPUT_READ, jabber_bs_recv_handshake, bt ); + bt->tf->watch_in = b_input_add( fd, B_EV_IO_READ, jabber_bs_recv_handshake, bt ); bt->tf->watch_out = 0; return FALSE; @@ -588,7 +588,7 @@ void jabber_bs_recv_answer_request( struct bs_transfer *bt ) bt->sh->port ); tf->ft->data = tf; - tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_recv_read, bt ); + tf->watch_in = b_input_add( tf->fd, B_EV_IO_READ, jabber_bs_recv_read, bt ); tf->ft->write_request = jabber_bs_recv_write_request; reply = xt_new_node( "streamhost-used", NULL, NULL ); @@ -630,7 +630,7 @@ gboolean jabber_bs_recv_read( gpointer data, gint fd, b_input_condition cond ) if( ( ret == -1 ) && ( errno == EAGAIN ) ) { - tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_recv_read, bt ); + tf->watch_in = b_input_add( tf->fd, B_EV_IO_READ, jabber_bs_recv_read, bt ); return FALSE; } } @@ -706,7 +706,7 @@ gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int l if( tf->byteswritten >= ft->file_size ) imcb_file_finished( ft ); else - bt->tf->watch_out = b_input_add( tf->fd, GAIM_INPUT_WRITE, jabber_bs_send_can_write, bt ); + bt->tf->watch_out = b_input_add( tf->fd, B_EV_IO_WRITE, jabber_bs_send_can_write, bt ); return TRUE; } @@ -917,7 +917,7 @@ void jabber_si_set_proxies( struct bs_transfer *bt ) strcpy( sh->port, port ); bt->streamhosts = g_slist_append( bt->streamhosts, sh ); - bt->tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_send_handshake, bt ); + bt->tf->watch_in = b_input_add( tf->fd, B_EV_IO_READ, jabber_bs_send_handshake, bt ); bt->connect_timeout = b_timeout_add( JABBER_BS_LISTEN_TIMEOUT * 1000, jabber_bs_connect_timeout, bt ); } else { imcb_log( tf->ic, "Transferring file %s: couldn't listen locally(non fatal, check your ft_listen setting in bitlbee.conf): %s", @@ -1054,7 +1054,7 @@ gboolean jabber_bs_send_handshake( gpointer data, gint fd, b_input_condition con bt->phase = BS_PHASE_CONNECTED; - bt->tf->watch_in = b_input_add( fd, GAIM_INPUT_READ, jabber_bs_send_handshake, bt ); + bt->tf->watch_in = b_input_add( fd, B_EV_IO_READ, jabber_bs_send_handshake, bt ); return FALSE; } case BS_PHASE_CONNECTED: diff --git a/protocols/msn/invitation.c b/protocols/msn/invitation.c index d2b2a5c8..9f8b9a6e 100644 --- a/protocols/msn/invitation.c +++ b/protocols/msn/invitation.c @@ -208,7 +208,7 @@ gboolean msn_ftps_connected( gpointer data, gint fd, b_input_condition cond ) fd = msn_file->fd; sock_make_nonblocking( fd ); - msn_file->r_event_id = b_input_add( fd, GAIM_INPUT_READ, msn_ftp_read, file ); + msn_file->r_event_id = b_input_add( fd, B_EV_IO_READ, msn_ftp_read, file ); return FALSE; } @@ -229,7 +229,7 @@ void msn_invitations_accept( msn_filetransfer_t *msn_file, struct msn_switchboar return; } - msn_file->r_event_id = b_input_add( msn_file->fd, GAIM_INPUT_READ, msn_ftps_connected, file ); + msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file ); g_snprintf( buf, sizeof( buf ), "IP-Address: %s\r\n" @@ -317,7 +317,7 @@ gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond ) return FALSE; sock_make_nonblocking( msn_file->fd ); - msn_file->r_event_id = b_input_add( msn_file->fd, GAIM_INPUT_READ, msn_ftp_read, file ); + msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file ); return FALSE; } @@ -414,7 +414,7 @@ gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len ) if( ( msn_file->sbufpos < MSNFTP_PSIZE ) && ( msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size ) ) { if( !msn_file->w_event_id ) - msn_file->w_event_id = b_input_add( msn_file->fd, GAIM_INPUT_WRITE, msn_ftp_send, file ); + msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); return TRUE; } @@ -451,7 +451,7 @@ gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len ) } else { /* we might already be listening if this is data from an overflow */ if( !msn_file->w_event_id ) - msn_file->w_event_id = b_input_add( msn_file->fd, GAIM_INPUT_WRITE, msn_ftp_send, file ); + msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); } return TRUE; @@ -616,7 +616,7 @@ gboolean msn_ftpr_write_request( file_transfer_t *file ) } msn_file->r_event_id = - b_input_add( msn_file->fd, GAIM_INPUT_READ, msn_ftp_read, file ); + b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file ); return TRUE; } -- cgit v1.2.3 From f60079b74053a53da3720b992c603fddf75ff1dd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 25 May 2010 23:26:54 +0100 Subject: Allow one to run the configure script from a different directory and put all build files in there. I need this to properly make Debian package variants (i.e. libpurple and native). --- protocols/Makefile | 5 ++++- protocols/jabber/Makefile | 5 ++++- protocols/msn/Makefile | 5 ++++- protocols/oscar/Makefile | 6 +++++- protocols/purple/Makefile | 5 ++++- protocols/twitter/Makefile | 5 ++++- protocols/yahoo/Makefile | 5 ++++- 7 files changed, 29 insertions(+), 7 deletions(-) (limited to 'protocols') diff --git a/protocols/Makefile b/protocols/Makefile index 18d79e8d..57fcd7eb 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -7,6 +7,9 @@ ### DEFINITIONS -include ../Makefile.settings +ifdef SRCDIR +SRCDIR := $(SRCDIR)protocols/ +endif # [SH] Program variables objects = nogaim.o @@ -48,6 +51,6 @@ protocols.o: $(objects) $(subdirs) $(objects): ../Makefile.settings Makefile -$(objects): %.o: %.c +$(objects): %.o: $(SRCDIR)%.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 78a02696..912ea702 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -7,6 +7,9 @@ ### DEFINITIONS -include ../../Makefile.settings +ifdef SRCDIR +SRCDIR := $(SRCDIR)protocols/jabber/ +endif # [SH] Program variables objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o @@ -32,7 +35,7 @@ distclean: clean $(objects): ../../Makefile.settings Makefile -$(objects): %.o: %.c +$(objects): %.o: $(SRCDIR)%.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index 5d199b9e..1de755a8 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -7,6 +7,9 @@ ### DEFINITIONS -include ../../Makefile.settings +ifdef SRCDIR +SRCDIR := $(SRCDIR)protocols/msn/ +endif # [SH] Program variables objects = invitation.o msn.o msn_util.o ns.o passport.o sb.o tables.o @@ -32,7 +35,7 @@ distclean: clean $(objects): ../../Makefile.settings Makefile -$(objects): %.o: %.c +$(objects): %.o: $(SRCDIR)%.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/protocols/oscar/Makefile b/protocols/oscar/Makefile index 2792f22a..0ec7436b 100644 --- a/protocols/oscar/Makefile +++ b/protocols/oscar/Makefile @@ -7,6 +7,10 @@ ### DEFINITIONS -include ../../Makefile.settings +ifdef SRCDIR +SRCDIR := $(SRCDIR)protocols/oscar/ +CFLAGS += -I$(SRCDIR) +endif # [SH] Program variables objects = admin.o auth.o bos.o buddylist.o chat.o chatnav.o conn.o icq.o im.o info.o misc.o msgcookie.o rxhandlers.o rxqueue.o search.o service.o snac.o ssi.o stats.o tlv.o txqueue.o oscar_util.o oscar.o @@ -32,7 +36,7 @@ distclean: clean $(objects): ../../Makefile.settings Makefile -$(objects): %.o: %.c +$(objects): %.o: $(SRCDIR)%.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/protocols/purple/Makefile b/protocols/purple/Makefile index 403db799..97a5bb6a 100644 --- a/protocols/purple/Makefile +++ b/protocols/purple/Makefile @@ -7,6 +7,9 @@ ### DEFINITIONS -include ../../Makefile.settings +ifdef SRCDIR +SRCDIR := $(SRCDIR)protocols/purple/ +endif # [SH] Program variables objects = ft.o purple.o @@ -32,7 +35,7 @@ distclean: clean $(objects): ../../Makefile.settings Makefile -$(objects): %.o: %.c +$(objects): %.o: $(SRCDIR)%.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/protocols/twitter/Makefile b/protocols/twitter/Makefile index ca1e4695..8a4b97f9 100644 --- a/protocols/twitter/Makefile +++ b/protocols/twitter/Makefile @@ -7,6 +7,9 @@ ### DEFINITIONS -include ../../Makefile.settings +ifdef SRCDIR +SRCDIR := $(SRCDIR)protocols/twitter/ +endif # [SH] Program variables objects = twitter.o twitter_http.o twitter_lib.o @@ -32,7 +35,7 @@ distclean: clean $(objects): ../../Makefile.settings Makefile -$(objects): %.o: %.c +$(objects): %.o: $(SRCDIR)%.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/protocols/yahoo/Makefile b/protocols/yahoo/Makefile index b4fe56e2..20ecce71 100644 --- a/protocols/yahoo/Makefile +++ b/protocols/yahoo/Makefile @@ -7,6 +7,9 @@ ### DEFINITIONS -include ../../Makefile.settings +ifdef SRCDIR +SRCDIR := $(SRCDIR)protocols/yahoo/ +endif # [SH] Program variables objects = yahoo.o crypt.o libyahoo2.o yahoo_fn.o yahoo_httplib.o yahoo_util.o @@ -32,7 +35,7 @@ distclean: clean $(objects): ../../Makefile.settings Makefile -$(objects): %.o: %.c +$(objects): %.o: $(SRCDIR)%.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ -- cgit v1.2.3 From 3dc6d86076dbea16c313bb87aa2f37166f289a8e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 2 Jun 2010 09:47:18 +0100 Subject: Disable old-style ICQ authentication. It looks like AOL or whoever is slowly taking down support for it. Just to be sure, it can be re-enabled with a setting, I'll remove that after the next release. --- protocols/oscar/auth.c | 3 ++- protocols/oscar/oscar.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/oscar/auth.c b/protocols/oscar/auth.c index eb6a9d64..0f7c8d0f 100644 --- a/protocols/oscar/auth.c +++ b/protocols/oscar/auth.c @@ -119,11 +119,12 @@ int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn) aim_frame_t *fr; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; + struct im_connection *ic = sess->aux_data; if (!sess || !conn || !sn) return -EINVAL; - if ((sn[0] >= '0') && (sn[0] <= '9')) + if (isdigit(sn[0]) && set_getbool(&ic->acc->set, "old_icq_auth")) return goddamnicq(sess, conn, sn); sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 9f33f320..9602a496 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -373,6 +373,7 @@ static void oscar_init(account_t *acc) if (isdigit(acc->user[0])) { set_add(&acc->set, "ignore_auth_requests", "false", set_eval_bool, acc); + set_add(&acc->set, "old_icq_auth", "false", set_eval_bool, acc); } s = set_add(&acc->set, "server", AIM_DEFAULT_LOGIN_SERVER, set_eval_account, acc); -- cgit v1.2.3