diff options
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/Makefile | 2 | ||||
-rw-r--r-- | protocols/jabber/Makefile | 4 | ||||
-rw-r--r-- | protocols/jabber/io.c | 12 | ||||
-rw-r--r-- | protocols/jabber/iq.c | 27 | ||||
-rw-r--r-- | protocols/jabber/jabber.c | 1 | ||||
-rw-r--r-- | protocols/jabber/jabber_util.c | 8 | ||||
-rw-r--r-- | protocols/jabber/sasl.c | 27 | ||||
-rw-r--r-- | protocols/jabber/xmltree.c | 589 | ||||
-rw-r--r-- | protocols/jabber/xmltree.h | 97 | ||||
-rw-r--r-- | protocols/msn/Makefile | 2 | ||||
-rw-r--r-- | protocols/msn/msn.h | 2 | ||||
-rw-r--r-- | protocols/msn/msn_util.c | 8 | ||||
-rw-r--r-- | protocols/msn/ns.c | 30 | ||||
-rw-r--r-- | protocols/msn/passport.c | 280 | ||||
-rw-r--r-- | protocols/msn/passport.h | 93 | ||||
-rw-r--r-- | protocols/nogaim.c | 17 | ||||
-rw-r--r-- | protocols/nogaim.h | 3 | ||||
-rw-r--r-- | protocols/oscar/Makefile | 2 | ||||
-rw-r--r-- | protocols/oscar/oscar.c | 18 | ||||
-rw-r--r-- | protocols/yahoo/Makefile | 2 | ||||
-rw-r--r-- | protocols/yahoo/libyahoo2.c | 4 | ||||
-rw-r--r-- | protocols/yahoo/yahoo.c | 10 |
22 files changed, 314 insertions, 924 deletions
diff --git a/protocols/Makefile b/protocols/Makefile index f7d76e0f..18d79e8d 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -26,7 +26,7 @@ LFLAGS += -r # [SH] Phony targets all: protocols.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 21d7ef07..891df5eb 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o si.o s5bytestream.o +objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o si.o s5bytestream.o CFLAGS += -Wall LFLAGS += -r @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: jabber_mod.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 86c216ef..10efad37 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -240,8 +240,13 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition return FALSE; } - /* EAGAIN/etc or a successful read. */ - return TRUE; + if( ssl_pending( jd->ssl ) ) + /* OpenSSL empties the TCP buffers completely but may keep some + data in its internap buffers. select() won't see that, but + ssl_pending() does. */ + return jabber_read_callback( data, fd, cond ); + else + return TRUE; } gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) @@ -520,8 +525,7 @@ gboolean jabber_start_stream( struct im_connection *ic ) /* We'll start our stream now, so prepare everything to receive one from the server too. */ xt_free( jd->xt ); /* In case we're RE-starting. */ - jd->xt = xt_new( ic ); - jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers; + 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 ); diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index d45b7625..22aa3e7c 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -533,6 +533,8 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no return XT_HANDLED; } +static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); + int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ) { struct xt_node *node; @@ -548,13 +550,36 @@ int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ) node = xt_new_node( "query", NULL, node ); xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "set", NULL, node ); + jabber_cache_add( ic, node, jabber_add_to_roster_callback ); st = jabber_write_packet( ic, node ); - xt_free_node( node ); return st; } +static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +{ + char *s, *jid = NULL; + struct xt_node *c; + + if( ( c = xt_find_node( orig->children, "query" ) ) && + ( c = xt_find_node( c->children, "item" ) ) && + ( jid = xt_find_attr( c, "jid" ) ) && + ( s = xt_find_attr( node, "type" ) ) && + strcmp( s, "result" ) == 0 ) + { + if( imcb_find_buddy( ic, jid ) == NULL ) + imcb_add_buddy( ic, jid, NULL ); + } + else + { + imcb_log( ic, "Error while adding `%s' to your contact list.", + jid ? jid : "(unknown handle)" ); + } + + return XT_HANDLED; +} + int jabber_remove_from_roster( struct im_connection *ic, char *handle ) { struct xt_node *node; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 07d760a5..04d6f906 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -266,6 +266,7 @@ static void jabber_logout( struct im_connection *ic ) xt_free( jd->xt ); + g_free( jd->cached_id_prefix ); g_free( jd->away_message ); g_free( jd->username ); g_free( jd ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index c8470b57..23a3010f 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -249,8 +249,10 @@ struct jabber_buddy_ask_data char *realname; }; -static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla ) +static void jabber_buddy_ask_yes( void *data ) { + struct jabber_buddy_ask_data *bla = data; + presence_send_request( bla->ic, bla->handle, "subscribed" ); if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) @@ -260,8 +262,10 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla g_free( bla ); } -static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla ) +static void jabber_buddy_ask_no( void *data ) { + struct jabber_buddy_ask_data *bla = data; + presence_send_request( bla->ic, bla->handle, "subscribed" ); g_free( bla->handle ); diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 87059051..53248ef3 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -21,6 +21,8 @@ * * \***************************************************************************/ +#include <ctype.h> + #include "jabber.h" #include "base64.h" @@ -106,12 +108,17 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) return XT_HANDLED; } -static char *sasl_get_part( char *data, char *field ) +/* Non-static function, but not mentioned in jabber.h because it's for internal + use, just that the unittest should be able to reach it... */ +char *sasl_get_part( char *data, char *field ) { int i, len; len = strlen( field ); + while( isspace( *data ) || *data == ',' ) + data ++; + if( g_strncasecmp( data, field, len ) == 0 && data[len] == '=' ) { i = strlen( field ) + 1; @@ -128,13 +135,19 @@ static char *sasl_get_part( char *data, char *field ) i ++; } - /* If we got a comma, we got a new field. Check it. */ - if( data[i] == ',' && - g_strncasecmp( data + i + 1, field, len ) == 0 && - data[i+len+1] == '=' ) + /* If we got a comma, we got a new field. Check it, + find the next key after it. */ + if( data[i] == ',' ) { - i += len + 2; - break; + while( isspace( data[i] ) || data[i] == ',' ) + i ++; + + if( g_strncasecmp( data + i, field, len ) == 0 && + data[i+len] == '=' ) + { + i += len + 1; + break; + } } } } diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c deleted file mode 100644 index 62549eb5..00000000 --- a/protocols/jabber/xmltree.c +++ /dev/null @@ -1,589 +0,0 @@ -/***************************************************************************\ -* * -* BitlBee - An IRC to IM gateway * -* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * -* * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * -* * -* This library is free software; you can redistribute it and/or * -* modify it under the terms of the GNU Lesser General Public * -* License as published by the Free Software Foundation, version * -* 2.1. * -* * -* This library 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 * -* Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * -* * -****************************************************************************/ - -#include <glib.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> -#include <stdio.h> - -#include "xmltree.h" - -static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) -{ - struct xt_parser *xt = data; - struct xt_node *node = g_new0( struct xt_node, 1 ), *nt; - int i; - - node->parent = xt->cur; - node->name = g_strdup( element_name ); - - /* First count the number of attributes */ - for( i = 0; attr_names[i]; i ++ ); - - /* Then allocate a NULL-terminated array. */ - node->attr = g_new0( struct xt_attr, i + 1 ); - - /* And fill it, saving one variable by starting at the end. */ - for( i --; i >= 0; i -- ) - { - node->attr[i].key = g_strdup( attr_names[i] ); - node->attr[i].value = g_strdup( attr_values[i] ); - } - - /* Add it to the linked list of children nodes, if we have a current - node yet. */ - if( xt->cur ) - { - if( xt->cur->children ) - { - for( nt = xt->cur->children; nt->next; nt = nt->next ); - nt->next = node; - } - else - { - xt->cur->children = node; - } - } - else if( xt->root ) - { - /* ERROR situation: A second root-element??? */ - } - - /* Now this node will be the new current node. */ - xt->cur = node; - /* And maybe this is the root? */ - if( xt->root == NULL ) - xt->root = node; -} - -static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) -{ - struct xt_parser *xt = data; - struct xt_node *node = xt->cur; - - if( node == NULL ) - return; - - /* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */ - node->text = g_renew( char, node->text, node->text_len + text_len + 1 ); - memcpy( node->text + node->text_len, text, text_len ); - node->text_len += text_len; - /* Zero termination is always nice to have. */ - node->text[node->text_len] = 0; -} - -static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) -{ - struct xt_parser *xt = data; - - xt->cur->flags |= XT_COMPLETE; - xt->cur = xt->cur->parent; -} - -GMarkupParser xt_parser_funcs = -{ - xt_start_element, - xt_end_element, - xt_text, - NULL, - NULL -}; - -struct xt_parser *xt_new( gpointer data ) -{ - struct xt_parser *xt = g_new0( struct xt_parser, 1 ); - - xt->data = data; - xt_reset( xt ); - - return xt; -} - -/* Reset the parser, flush everything we have so far. For example, we need - this for XMPP when doing TLS/SASL to restart the stream. */ -void xt_reset( struct xt_parser *xt ) -{ - if( xt->parser ) - g_markup_parse_context_free( xt->parser ); - - xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL ); - - if( xt->root ) - { - xt_free_node( xt->root ); - xt->root = NULL; - xt->cur = NULL; - } -} - -/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on - end-of-stream and 1 otherwise. */ -int xt_feed( struct xt_parser *xt, char *text, int text_len ) -{ - if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) ) - { - return -1; - } - - return !( xt->root && xt->root->flags & XT_COMPLETE ); -} - -/* Find completed nodes and see if a handler has to be called. Passing - a node isn't necessary if you want to start at the root, just pass - NULL. This second argument is needed for recursive calls. */ -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) -{ - struct xt_node *c; - xt_status st; - int i; - - /* Just in case someone likes infinite loops... */ - if( xt->root == NULL ) - return 0; - - if( node == NULL ) - return xt_handle( xt, xt->root, depth ); - - if( depth != 0 ) - for( c = node->children; c; c = c->next ) - if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) ) - return 0; - - if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) - { - for( i = 0; xt->handlers[i].func; i ++ ) - { - /* This one is fun! \o/ */ - - /* If handler.name == NULL it means it should always match. */ - if( ( xt->handlers[i].name == NULL || - /* If it's not, compare. There should always be a name. */ - g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && - /* If handler.parent == NULL, it's a match. */ - ( xt->handlers[i].parent == NULL || - /* If there's a parent node, see if the name matches. */ - ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : - /* If there's no parent, the handler should mention <root> as a parent. */ - g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) - { - st = xt->handlers[i].func( node, xt->data ); - - if( st == XT_ABORT ) - return 0; - else if( st != XT_NEXT ) - break; - } - } - - node->flags |= XT_SEEN; - } - - return 1; -} - -/* Garbage collection: Cleans up all nodes that are handled. Useful for - streams because there's no reason to keep a complete packet history - in memory. */ -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ) -{ - struct xt_node *c, *prev; - - if( !xt || !xt->root ) - return; - - if( node == NULL ) - return xt_cleanup( xt, xt->root, depth ); - - if( node->flags & XT_SEEN && node == xt->root ) - { - xt_free_node( xt->root ); - xt->root = xt->cur = NULL; - /* xt->cur should be NULL already, BTW... */ - - return; - } - - /* c contains the current node, prev the previous node (or NULL). - I admit, this one's pretty horrible. */ - for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children ) - { - if( c->flags & XT_SEEN ) - { - /* Remove the node from the linked list. */ - if( prev ) - prev->next = c->next; - else - node->children = c->next; - - xt_free_node( c ); - - /* Since the for loop wants to get c->next, make sure - c points at something that exists (and that c->next - will actually be the next item we should check). c - can be NULL now, if we just removed the first item. - That explains the ? thing in for(). */ - c = prev; - } - else - { - /* This node can't be cleaned up yet, but maybe a - subnode can. */ - if( depth != 0 ) - xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth ); - } - } -} - -static void xt_to_string_real( struct xt_node *node, GString *str ) -{ - char *buf; - struct xt_node *c; - int i; - - g_string_append_printf( str, "<%s", node->name ); - - for( i = 0; node->attr[i].key; i ++ ) - { - buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value ); - g_string_append( str, buf ); - g_free( buf ); - } - - if( node->text == NULL && node->children == NULL ) - { - g_string_append( str, "/>" ); - return; - } - - g_string_append( str, ">" ); - if( node->text_len > 0 ) - { - buf = g_markup_escape_text( node->text, node->text_len ); - g_string_append( str, buf ); - g_free( buf ); - } - - for( c = node->children; c; c = c->next ) - xt_to_string_real( c, str ); - - g_string_append_printf( str, "</%s>", node->name ); -} - -char *xt_to_string( struct xt_node *node ) -{ - GString *ret; - char *real; - - ret = g_string_new( "" ); - xt_to_string_real( node, ret ); - - real = ret->str; - g_string_free( ret, FALSE ); - - return real; -} - -#ifdef DEBUG -void xt_print( struct xt_node *node ) -{ - int i; - struct xt_node *c; - - /* Indentation */ - for( c = node; c->parent; c = c->parent ) - printf( "\t" ); - - /* Start the tag */ - printf( "<%s", node->name ); - - /* Print the attributes */ - for( i = 0; node->attr[i].key; i ++ ) - printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) ); - - /* /> in case there's really *nothing* inside this tag, otherwise - just >. */ - /* If this tag doesn't have any content at all... */ - if( node->text == NULL && node->children == NULL ) - { - printf( "/>\n" ); - return; - /* Then we're finished! */ - } - - /* Otherwise... */ - printf( ">" ); - - /* Only print the text if it contains more than whitespace (TEST). */ - if( node->text_len > 0 ) - { - for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ ); - if( node->text[i] ) - printf( "%s", g_markup_escape_text( node->text, -1 ) ); - } - - if( node->children ) - printf( "\n" ); - - for( c = node->children; c; c = c->next ) - xt_print( c ); - - if( node->children ) - for( c = node; c->parent; c = c->parent ) - printf( "\t" ); - - /* Non-empty tag is now finished. */ - printf( "</%s>\n", node->name ); -} -#endif - -struct xt_node *xt_dup( struct xt_node *node ) -{ - struct xt_node *dup = g_new0( struct xt_node, 1 ); - struct xt_node *c, *dc = NULL; - int i; - - /* Let's NOT copy the parent element here BTW! Only do it for children. */ - - dup->name = g_strdup( node->name ); - dup->flags = node->flags; - if( node->text ) - { - dup->text = g_memdup( node->text, node->text_len + 1 ); - dup->text_len = node->text_len; - } - - /* Count the number of attributes and allocate the new array. */ - for( i = 0; node->attr[i].key; i ++ ); - dup->attr = g_new0( struct xt_attr, i + 1 ); - - /* Copy them all! */ - for( i --; i >= 0; i -- ) - { - dup->attr[i].key = g_strdup( node->attr[i].key ); - dup->attr[i].value = g_strdup( node->attr[i].value ); - } - - /* This nice mysterious loop takes care of the children. */ - for( c = node->children; c; c = c->next ) - { - if( dc == NULL ) - dc = dup->children = xt_dup( c ); - else - dc = ( dc->next = xt_dup( c ) ); - - dc->parent = dup; - } - - return dup; -} - -/* Frees a node. This doesn't clean up references to itself from parents! */ -void xt_free_node( struct xt_node *node ) -{ - int i; - - if( !node ) - return; - - g_free( node->name ); - g_free( node->text ); - - for( i = 0; node->attr[i].key; i ++ ) - { - g_free( node->attr[i].key ); - g_free( node->attr[i].value ); - } - g_free( node->attr ); - - while( node->children ) - { - struct xt_node *next = node->children->next; - - xt_free_node( node->children ); - node->children = next; - } - - g_free( node ); -} - -void xt_free( struct xt_parser *xt ) -{ - if( !xt ) - return; - - if( xt->root ) - xt_free_node( xt->root ); - - g_markup_parse_context_free( xt->parser ); - - g_free( xt ); -} - -/* To find a node's child with a specific name, pass the node's children - list, not the node itself! The reason you have to do this by hand: So - that you can also use this function as a find-next. */ -struct xt_node *xt_find_node( struct xt_node *node, const char *name ) -{ - while( node ) - { - if( g_strcasecmp( node->name, name ) == 0 ) - break; - - node = node->next; - } - - return node; -} - -char *xt_find_attr( struct xt_node *node, const char *key ) -{ - int i; - - if( !node ) - return NULL; - - for( i = 0; node->attr[i].key; i ++ ) - if( g_strcasecmp( node->attr[i].key, key ) == 0 ) - break; - - return node->attr[i].value; -} - -struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ) -{ - struct xt_node *node, *c; - - node = g_new0( struct xt_node, 1 ); - node->name = g_strdup( name ); - node->children = children; - node->attr = g_new0( struct xt_attr, 1 ); - - if( text ) - { - node->text_len = strlen( text ); - node->text = g_memdup( text, node->text_len + 1 ); - } - - for( c = children; c; c = c->next ) - { - if( c->parent != NULL ) - { - /* ERROR CONDITION: They seem to have a parent already??? */ - } - - c->parent = node; - } - - return node; -} - -void xt_add_child( struct xt_node *parent, struct xt_node *child ) -{ - struct xt_node *node; - - /* This function can actually be used to add more than one child, so - do handle this properly. */ - for( node = child; node; node = node->next ) - { - if( node->parent != NULL ) - { - /* ERROR CONDITION: They seem to have a parent already??? */ - } - - node->parent = parent; - } - - if( parent->children == NULL ) - { - parent->children = child; - } - else - { - for( node = parent->children; node->next; node = node->next ); - node->next = child; - } -} - -void xt_add_attr( struct xt_node *node, const char *key, const char *value ) -{ - int i; - - /* Now actually it'd be nice if we can also change existing attributes - (which actually means this function doesn't have the right name). - So let's find out if we have this attribute already... */ - for( i = 0; node->attr[i].key; i ++ ) - if( strcmp( node->attr[i].key, key ) == 0 ) - break; - - if( node->attr[i].key == NULL ) - { - /* If not, allocate space for a new attribute. */ - node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); - node->attr[i].key = g_strdup( key ); - node->attr[i+1].key = NULL; - } - else - { - /* Otherwise, free the old value before setting the new one. */ - g_free( node->attr[i].value ); - } - - node->attr[i].value = g_strdup( value ); -} - -int xt_remove_attr( struct xt_node *node, const char *key ) -{ - int i, last; - - for( i = 0; node->attr[i].key; i ++ ) - if( strcmp( node->attr[i].key, key ) == 0 ) - break; - - /* If we didn't find the attribute... */ - if( node->attr[i].key == NULL ) - return 0; - - g_free( node->attr[i].key ); - g_free( node->attr[i].value ); - - /* If it's the last, this is easy: */ - if( node->attr[i+1].key == NULL ) - { - node->attr[i].key = node->attr[i].value = NULL; - } - else /* It's also pretty easy, actually. */ - { - /* Find the last item. */ - for( last = i + 1; node->attr[last+1].key; last ++ ); - - node->attr[i] = node->attr[last]; - node->attr[last].key = NULL; - node->attr[last].value = NULL; - } - - /* Let's not bother with reallocating memory here. It takes time and - most packets don't stay in memory for long anyway. */ - - return 1; -} diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h deleted file mode 100644 index b8b61641..00000000 --- a/protocols/jabber/xmltree.h +++ /dev/null @@ -1,97 +0,0 @@ -/***************************************************************************\ -* * -* BitlBee - An IRC to IM gateway * -* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * -* * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * -* * -* This library is free software; you can redistribute it and/or * -* modify it under the terms of the GNU Lesser General Public * -* License as published by the Free Software Foundation, version * -* 2.1. * -* * -* This library 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 * -* Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * -* * -****************************************************************************/ - -#ifndef _XMLTREE_H -#define _XMLTREE_H - -typedef enum -{ - XT_COMPLETE = 1, /* </tag> reached */ - XT_SEEN = 2, /* Handler called (or not defined) */ -} xt_flags; - -typedef enum -{ - XT_ABORT, /* Abort, don't handle the rest anymore */ - XT_HANDLED, /* Handled this tag properly, go to the next one */ - XT_NEXT /* Try if there's another matching handler */ -} xt_status; - -struct xt_attr -{ - char *key, *value; -}; - -struct xt_node -{ - struct xt_node *parent; - struct xt_node *children; - - char *name; - struct xt_attr *attr; - char *text; - int text_len; - - struct xt_node *next; - xt_flags flags; -}; - -typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data ); - -struct xt_handler_entry -{ - char *name, *parent; - xt_handler_func func; -}; - -struct xt_parser -{ - GMarkupParseContext *parser; - struct xt_node *root; - struct xt_node *cur; - - struct xt_handler_entry *handlers; - gpointer data; - - GError *gerr; -}; - -struct xt_parser *xt_new( gpointer data ); -void xt_reset( struct xt_parser *xt ); -int xt_feed( struct xt_parser *xt, char *text, int text_len ); -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); -char *xt_to_string( struct xt_node *node ); -void xt_print( struct xt_node *node ); -struct xt_node *xt_dup( struct xt_node *node ); -void xt_free_node( struct xt_node *node ); -void xt_free( struct xt_parser *xt ); -struct xt_node *xt_find_node( struct xt_node *node, const char *name ); -char *xt_find_attr( struct xt_node *node, const char *key ); - -struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); -void xt_add_child( struct xt_node *parent, struct xt_node *child ); -void xt_add_attr( struct xt_node *node, const char *key, const char *value ); -int xt_remove_attr( struct xt_node *node, const char *key ); - -#endif diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index 3440658d..6a588613 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: msn_mod.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index c8f4f4c6..63759303 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -28,7 +28,7 @@ #define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r" #define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r" -#ifdef DEBUG +#ifdef DEBUG_MSN #define debug( text... ) imcb_log( ic, text ); #else #define debug( text... ) diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index fae2877d..58ad22f8 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -89,8 +89,10 @@ struct msn_buddy_ask_data char *realname; }; -static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla ) +static void msn_buddy_ask_yes( void *data ) { + struct msn_buddy_ask_data *bla = data; + msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) @@ -101,8 +103,10 @@ static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla ) g_free( bla ); } -static void msn_buddy_ask_no( gpointer w, struct msn_buddy_ask_data *bla ) +static void msn_buddy_ask_no( void *data ) { + struct msn_buddy_ask_data *bla = data; + msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname ); g_free( bla->handle ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 0bb84a74..ff7da6ed 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -33,7 +33,7 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); -static void msn_auth_got_passport_id( struct passport_reply *rep ); +static void msn_auth_got_passport_token( struct msn_auth_data *mad ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { @@ -213,7 +213,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) { /* Time for some Passport black magic... */ - if( !passport_get_id( msn_auth_got_passport_id, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) + if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) { imcb_error( ic, "Error while contacting Passport server" ); imc_logout( ic, TRUE ); @@ -673,22 +673,26 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int return( 1 ); } -static void msn_auth_got_passport_id( struct passport_reply *rep ) +static void msn_auth_got_passport_token( struct msn_auth_data *mad ) { - struct im_connection *ic = rep->data; - struct msn_data *md = ic->proto_data; - char *key = rep->result; - char buf[1024]; + struct im_connection *ic = mad->data; + struct msn_data *md; - if( key == NULL ) + /* Dead connection? */ + if( g_slist_find( msn_connections, ic ) == NULL ) + return; + + md = ic->proto_data; + if( mad->token ) { - imcb_error( ic, "Error during Passport authentication (%s)", - rep->error_string ? rep->error_string : "Unknown error" ); - imc_logout( ic, TRUE ); + char buf[1024]; + + g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token ); + msn_write( ic, buf, strlen( buf ) ); } else { - g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, key ); - msn_write( ic, buf, strlen( buf ) ); + imcb_error( ic, "Error during Passport authentication: %s", mad->error ); + imc_logout( ic, TRUE ); } } diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 9fe6a174..565d15f3 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -1,8 +1,7 @@ -/* passport.c +/** passport.c * - * Functions to login to microsoft passport service for Messenger - * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be> - * Copyright (C) 2004 Wilmer van der Gaast <wilmer@gaast.net> + * Functions to login to Microsoft Passport service for Messenger + * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -23,208 +22,149 @@ #include "passport.h" #include "msn.h" #include "bitlbee.h" +#include "url.h" +#include "misc.h" +#include "xmltree.h" #include <ctype.h> #include <errno.h> -#define MSN_BUF_LEN 8192 +static int passport_get_token_real( struct msn_auth_data *mad ); +static void passport_get_token_ready( struct http_request *req ); -static char *prd_cached = NULL; - -static int passport_get_id_real( gpointer func, gpointer data, char *header ); -static void passport_get_id_ready( struct http_request *req ); - -static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ); -static void passport_retrieve_dalogin_ready( struct http_request *req ); - -static char *passport_create_header( char *cookie, char *email, char *pwd ); -static void destroy_reply( struct passport_reply *rep ); - -int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ) -{ - char *header = passport_create_header( cookie, username, password ); - - if( prd_cached == NULL ) - return passport_retrieve_dalogin( func, data, header ); - else - return passport_get_id_real( func, data, header ); -} - -static int passport_get_id_real( gpointer func, gpointer data, char *header ) +int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie ) { - struct passport_reply *rep; - char *server, *dummy, *reqs; - struct http_request *req; - - rep = g_new0( struct passport_reply, 1 ); - rep->data = data; - rep->func = func; - rep->header = header; - - server = g_strdup( prd_cached ); - dummy = strchr( server, '/' ); - - if( dummy == NULL ) - { - destroy_reply( rep ); - return( 0 ); - } - - reqs = g_strdup_printf( "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header ); + struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 ); + int i; - *dummy = 0; - req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep ); + mad->username = g_strdup( username ); + mad->password = g_strdup( password ); + mad->cookie = g_strdup( cookie ); - g_free( server ); - g_free( reqs ); + mad->callback = func; + mad->data = data; - if( req == NULL ) - destroy_reply( rep ); + mad->url = g_strdup( SOAP_AUTHENTICATION_URL ); + mad->ttl = 3; /* Max. # of redirects. */ - return( req != NULL ); -} - -static void passport_get_id_ready( struct http_request *req ) -{ - struct passport_reply *rep = req->data; - - if( !g_slist_find( msn_connections, rep->data ) ) - { - destroy_reply( rep ); - return; - } + /* HTTP-escape stuff and s/,/&/ */ + http_decode( mad->cookie ); + for( i = 0; mad->cookie[i]; i ++ ) + if( mad->cookie[i] == ',' ) + mad->cookie[i] = '&'; - if( req->finished && req->reply_headers && req->status_code == 200 ) - { - char *dummy; - - if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) ) - { - char *responseend; - - dummy += strlen( "from-PP='" ); - responseend = strchr( dummy, '\'' ); - if( responseend ) - *responseend = 0; - - rep->result = g_strdup( dummy ); - } - else - { - rep->error_string = g_strdup( "Could not parse Passport server response" ); - } - } - else - { - rep->error_string = g_strdup_printf( "HTTP error: %s", - req->status_string ? req->status_string : "Unknown error" ); - } + /* Microsoft doesn't allow password longer than 16 chars and silently + fails authentication if you give the "full version" of your passwd. */ + if( strlen( mad->password ) > MAX_PASSPORT_PWLEN ) + mad->password[MAX_PASSPORT_PWLEN] = 0; - rep->func( rep ); - destroy_reply( rep ); + return passport_get_token_real( mad ); } -static char *passport_create_header( char *cookie, char *email, char *pwd ) +static int passport_get_token_real( struct msn_auth_data *mad ) { - char *buffer; - char *currenttoken; - char *email_enc, *pwd_enc; - - currenttoken = strstr( cookie, "lc=" ); - if( currenttoken == NULL ) - return NULL; + char *post_payload, *post_request; + struct http_request *req; + url_t url; - email_enc = g_new0( char, strlen( email ) * 3 + 1 ); - strcpy( email_enc, email ); - http_encode( email_enc ); + url_set( &url, mad->url ); - pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 ); - strcpy( pwd_enc, pwd ); - http_encode( pwd_enc ); + post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD, + mad->username, + mad->password, + mad->cookie ); - buffer = g_strdup_printf( "Authorization: Passport1.4 OrgVerb=GET," - "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom," - "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc, - currenttoken ); + post_request = g_strdup_printf( SOAP_AUTHENTICATION_REQUEST, + url.file, url.host, + (int) strlen( post_payload ), + post_payload ); + + req = http_dorequest( url.host, url.port, 1, post_request, + passport_get_token_ready, mad ); - g_free( email_enc ); - g_free( pwd_enc ); + g_free( post_request ); + g_free( post_payload ); - return buffer; + return req != NULL; } -static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header ) -{ - struct passport_reply *rep = g_new0( struct passport_reply, 1 ); - struct http_request *req; - - rep->data = data; - rep->func = func; - rep->header = header; - - req = http_dorequest_url( "https://nexus.passport.com/rdr/pprdr.asp", passport_retrieve_dalogin_ready, rep ); - - if( !req ) - destroy_reply( rep ); - - return( req != NULL ); -} +static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ); +static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data ); -static void passport_retrieve_dalogin_ready( struct http_request *req ) +static const struct xt_handler_entry passport_xt_handlers[] = { + { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", passport_xt_extract_token }, + { "S:Fault", "S:Envelope", passport_xt_handle_fault }, + { NULL, NULL, NULL } +}; + +static void passport_get_token_ready( struct http_request *req ) { - struct passport_reply *rep = req->data; - char *dalogin; - char *urlend; + struct msn_auth_data *mad = req->data; + struct xt_parser *parser; + + g_free( mad->url ); + g_free( mad->error ); + mad->url = mad->error = NULL; - if( !g_slist_find( msn_connections, rep->data ) ) + if( req->status_code == 200 ) { - destroy_reply( rep ); - return; + parser = xt_new( passport_xt_handlers, mad ); + xt_feed( parser, req->reply_body, req->body_size ); + xt_handle( parser, NULL, -1 ); + xt_free( parser ); } - - if( !req->finished || !req->reply_headers || req->status_code != 200 ) + else { - rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin: %s", - req->status_string ? req->status_string : "Unknown error" ); - goto failure; + mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code, + req->status_string ? req->status_string : "unknown" ); } - dalogin = strstr( req->reply_headers, "DALogin=" ); + if( mad->error == NULL && mad->token == NULL ) + mad->error = g_strdup( "Could not parse Passport server response" ); - if( !dalogin ) + if( mad->url && mad->token == NULL ) { - rep->error_string = g_strdup( "Parse error while fetching DALogin" ); - goto failure; + passport_get_token_real( mad ); } - - dalogin += strlen( "DALogin=" ); - urlend = strchr( dalogin, ',' ); - if( urlend ) - *urlend = 0; - - /* strip the http(s):// part from the url */ - urlend = strstr( urlend, "://" ); - if( urlend ) - dalogin = urlend + strlen( "://" ); - - if( prd_cached == NULL ) - prd_cached = g_strdup( dalogin ); - - if( passport_get_id_real( rep->func, rep->data, rep->header ) ) + else { - rep->header = NULL; - destroy_reply( rep ); - return; + mad->callback( mad ); + + g_free( mad->url ); + g_free( mad->username ); + g_free( mad->password ); + g_free( mad->cookie ); + g_free( mad->token ); + g_free( mad->error ); + g_free( mad ); } +} + +static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ) +{ + struct msn_auth_data *mad = data; + char *s; + + if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 ) + mad->token = g_memdup( node->text, node->text_len + 1 ); -failure: - rep->func( rep ); - destroy_reply( rep ); + return XT_HANDLED; } -static void destroy_reply( struct passport_reply *rep ) +static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data ) { - g_free( rep->result ); - g_free( rep->header ); - g_free( rep->error_string ); - g_free( rep ); + struct msn_auth_data *mad = data; + struct xt_node *code = xt_find_node( node->children, "faultcode" ); + struct xt_node *string = xt_find_node( node->children, "faultstring" ); + struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" ); + + if( redirect && redirect->text_len && mad->ttl-- > 0 ) + mad->url = g_memdup( redirect->text, redirect->text_len + 1 ); + + if( code == NULL || code->text_len == 0 ) + mad->error = g_strdup( "Unknown error" ); + else + mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ? + string->text : "no description available" ); + + return XT_HANDLED; } diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h index 9fd81a82..517d2e91 100644 --- a/protocols/msn/passport.h +++ b/protocols/msn/passport.h @@ -1,10 +1,7 @@ -#ifndef __PASSPORT_H__ -#define __PASSPORT_H__ /* passport.h * - * Functions to login to Microsoft Passport Service for Messenger - * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be>, - * Wilmer van der Gaast <wilmer@gaast.net> + * Functions to login to Microsoft Passport service for Messenger + * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -17,9 +14,15 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Thanks to http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener + for the specs! */ + +#ifndef __PASSPORT_H__ +#define __PASSPORT_H__ + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -32,15 +35,79 @@ #endif #include "nogaim.h" -struct passport_reply +#define MAX_PASSPORT_PWLEN 16 + +struct msn_auth_data { - void (*func)( struct passport_reply * ); - void *data; - char *result; - char *header; - char *error_string; + char *url; + int ttl; + + char *username; + char *password; + char *cookie; + + /* The end result, the only thing we'll really be interested in + once finished. */ + char *token; + char *error; /* Yeah, or that... */ + + void (*callback)( struct msn_auth_data *mad ); + gpointer data; }; -int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ); +#define SOAP_AUTHENTICATION_URL "https://loginnet.passport.com/RST.srf" + +#define SOAP_AUTHENTICATION_REQUEST \ +"POST %s HTTP/1.0\r\n" \ +"Accept: text/*\r\n" \ +"User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ +"Host: %s\r\n" \ +"Content-Length: %d\r\n" \ +"Cache-Control: no-cache\r\n" \ +"\r\n" \ +"%s" + +#define SOAP_AUTHENTICATION_PAYLOAD \ +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \ +"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">" \ + "<Header>" \ + "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">" \ + "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>" \ + "<ps:BinaryVersion>4</ps:BinaryVersion>" \ + "<ps:UIVersion>1</ps:UIVersion>" \ + "<ps:Cookies></ps:Cookies>" \ + "<ps:RequestParams>AQAAAAIAAABsYwQAAAAzMDg0</ps:RequestParams>" \ + "</ps:AuthInfo>" \ + "<wsse:Security>" \ + "<wsse:UsernameToken Id=\"user\">" \ + "<wsse:Username>%s</wsse:Username>" \ + "<wsse:Password>%s</wsse:Password>" \ + "</wsse:UsernameToken>" \ + "</wsse:Security>" \ + "</Header>" \ + "<Body>" \ + "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">" \ + "<wst:RequestSecurityToken Id=\"RST0\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>http://Passport.NET/tb</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "</wst:RequestSecurityToken>" \ + "<wst:RequestSecurityToken Id=\"RST1\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>messenger.msn.com</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>" \ + "</wst:RequestSecurityToken>" \ + "</ps:RequestMultipleSecurityTokens>" \ + "</Body>" \ +"</Envelope>" + +int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie ); #endif /* __PASSPORT_H__ */ diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 3ce15166..7466e93a 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -342,7 +342,8 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) /* dialogs.c */ -void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ) +void imcb_ask( struct im_connection *ic, char *msg, void *data, + query_callback doit, query_callback dont ) { query_add( ic->irc, ic, msg, doit, dont, data ); } @@ -494,18 +495,20 @@ struct show_got_added_data char *handle; }; -void show_got_added_no( gpointer w, struct show_got_added_data *data ) +void show_got_added_no( void *data ) { - g_free( data->handle ); + g_free( ((struct show_got_added_data*)data)->handle ); g_free( data ); } -void show_got_added_yes( gpointer w, struct show_got_added_data *data ) +void show_got_added_yes( void *data ) { - data->ic->acc->prpl->add_buddy( data->ic, data->handle, NULL ); - /* imcb_add_buddy( data->ic, NULL, data->handle, data->handle ); */ + struct show_got_added_data *sga = data; - return show_got_added_no( w, data ); + sga->ic->acc->prpl->add_buddy( sga->ic, sga->handle, NULL ); + /* imcb_add_buddy( sga->ic, NULL, sga->handle, sga->handle ); */ + + return show_got_added_no( data ); } void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 37232493..17da2b36 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -41,6 +41,7 @@ #include "bitlbee.h" #include "account.h" #include "proxy.h" +#include "query.h" #include "md5.h" #include "ft.h" @@ -264,7 +265,7 @@ G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ) G * - 'data' can be your custom struct - it will be passed to the callbacks. * - 'doit' or 'dont' will be called depending of the answer of the user. */ -G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); +G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, query_callback doit, query_callback dont ); G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ); /* Buddy management */ diff --git a/protocols/oscar/Makefile b/protocols/oscar/Makefile index 95e85ec2..2792f22a 100644 --- a/protocols/oscar/Makefile +++ b/protocols/oscar/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: oscar_mod.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 9e5de70a..7738c31f 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1083,8 +1083,8 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ return 1; } -void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv); -void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv); +void oscar_accept_chat(void *data); +void oscar_reject_chat(void *data); static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) { struct im_connection *ic = sess->aux_data; @@ -1118,7 +1118,8 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ return 1; } -static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { +static void gaim_icq_authgrant(void *data_) { + struct icq_auth *data = data_; char *uin, message; struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; @@ -1133,7 +1134,8 @@ static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { g_free(data); } -static void gaim_icq_authdeny(gpointer w, struct icq_auth *data) { +static void gaim_icq_authdeny(void *data_) { + struct icq_auth *data = data_; char *uin, *message; struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; @@ -2587,15 +2589,19 @@ struct groupchat *oscar_chat_with(struct im_connection * ic, char *who) return NULL; } -void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv) +void oscar_accept_chat(void *data) { + struct aim_chat_invitation * inv = data; + oscar_chat_join(inv->ic, inv->name, NULL, NULL); g_free(inv->name); g_free(inv); } -void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv) +void oscar_reject_chat(void *data) { + struct aim_chat_invitation * inv = data; + g_free(inv->name); g_free(inv); } diff --git a/protocols/yahoo/Makefile b/protocols/yahoo/Makefile index 2cfd147b..b4fe56e2 100644 --- a/protocols/yahoo/Makefile +++ b/protocols/yahoo/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: yahoo_mod.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index ce38bc73..80d88a85 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -736,7 +736,7 @@ static void yahoo_send_packet(struct yahoo_input_data *yid, struct yahoo_packet data = y_new0(unsigned char, len + 1); memcpy(data + pos, "YMSG", 4); pos += 4; - pos += yahoo_put16(data + pos, 0x0a00); + pos += yahoo_put16(data + pos, 0x000c); pos += yahoo_put16(data + pos, 0x0000); pos += yahoo_put16(data + pos, pktlen + extra_pad); pos += yahoo_put16(data + pos, pkt->service); @@ -3350,7 +3350,7 @@ static void yahoo_process_search_connection(struct yahoo_input_data *yid, int ov yct->age = atoi(cp); break; case 5: - if(cp != "\005") + if(strcmp(cp, "5") != 0) yct->location = cp; k = 0; break; diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 9f9ffcf7..ab30df4d 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -314,7 +314,7 @@ static void byahoo_chat_invite( struct groupchat *c, char *who, char *msg ) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; - yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ); + yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ? msg : "" ); } static void byahoo_chat_leave( struct groupchat *c ) @@ -796,16 +796,20 @@ int ext_yahoo_connect(const char *host, int port) return -1; } -static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) +static void byahoo_accept_conf( void *data ) { + struct byahoo_conf_invitation *inv = data; + yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name ); imcb_chat_add_buddy( inv->c, inv->ic->acc->user ); g_free( inv->name ); g_free( inv ); } -static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv ) +static void byahoo_reject_conf( void *data ) { + struct byahoo_conf_invitation *inv = data; + yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" ); imcb_chat_free( inv->c ); g_free( inv->name ); |