aboutsummaryrefslogtreecommitdiffstats
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/jabber/Makefile2
-rw-r--r--protocols/jabber/io.c12
-rw-r--r--protocols/jabber/jabber.c55
-rw-r--r--protocols/jabber/jabber.h6
-rw-r--r--protocols/jabber/jabber_util.c67
-rw-r--r--protocols/jabber/message.c17
-rw-r--r--protocols/jabber/xmltree.c589
-rw-r--r--protocols/jabber/xmltree.h97
-rw-r--r--protocols/msn/msn.h2
-rw-r--r--protocols/msn/msn_util.c8
-rw-r--r--protocols/msn/ns.c77
-rw-r--r--protocols/msn/passport.c280
-rw-r--r--protocols/msn/passport.h93
-rw-r--r--protocols/nogaim.c17
-rw-r--r--protocols/nogaim.h8
-rw-r--r--protocols/oscar/oscar.c98
-rw-r--r--protocols/yahoo/libyahoo2.c17
-rw-r--r--protocols/yahoo/yahoo.c19
-rw-r--r--protocols/yahoo/yahoo_httplib.c2
19 files changed, 459 insertions, 1007 deletions
diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile
index 3ce78127..e7a505ba 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
+objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o
CFLAGS += -Wall
LFLAGS += -r
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/jabber.c b/protocols/jabber/jabber.c
index dac18bae..5fb2c4fc 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -32,15 +32,33 @@
#include "bitlbee.h"
#include "jabber.h"
#include "md5.h"
-#include "base64.h"
GSList *jabber_connections;
+/* First enty is the default */
+static const int jabber_port_list[] = {
+ 5222,
+ 5223,
+ 5220,
+ 5221,
+ 5224,
+ 5225,
+ 5226,
+ 5227,
+ 5228,
+ 5229,
+ 80,
+ 443,
+ 0
+};
+
static void jabber_init( account_t *acc )
{
set_t *s;
+ char str[16];
- s = set_add( &acc->set, "port", JABBER_PORT_DEFAULT, set_eval_int, acc );
+ g_snprintf( str, sizeof( str ), "%d", jabber_port_list[0] );
+ s = set_add( &acc->set, "port", str, set_eval_int, acc );
s->flags |= ACC_SET_OFFLINE_ONLY;
s = set_add( &acc->set, "priority", "0", set_eval_priority, acc );
@@ -71,6 +89,7 @@ static void jabber_login( account_t *acc )
struct jabber_data *jd = g_new0( struct jabber_data, 1 );
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
@@ -176,11 +195,13 @@ static void jabber_login( account_t *acc )
imcb_log( ic, "Connecting" );
- if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN ||
- set_getint( &acc->set, "port" ) > JABBER_PORT_MAX )
+ for( i = 0; jabber_port_list[i] > 0; i ++ )
+ if( set_getint( &acc->set, "port" ) == jabber_port_list[i] )
+ break;
+
+ if( jabber_port_list[i] == 0 )
{
- imcb_log( ic, "Incorrect port number, must be in the %d-%d range",
- JABBER_PORT_MIN, JABBER_PORT_MAX );
+ imcb_log( ic, "Illegal port number" );
imc_logout( ic, FALSE );
return;
}
@@ -218,24 +239,20 @@ static void jabber_login( account_t *acc )
jabber_generate_id_hash( jd );
}
+/* This generates an unfinished md5_state_t variable. Every time we generate
+ an ID, we finish the state by adding a sequence number and take the hash. */
static void jabber_generate_id_hash( struct jabber_data *jd )
{
- md5_state_t id_hash;
- md5_byte_t binbuf[16];
+ md5_byte_t binbuf[4];
char *s;
- md5_init( &id_hash );
- md5_append( &id_hash, (unsigned char *) jd->username, strlen( jd->username ) );
- md5_append( &id_hash, (unsigned char *) jd->server, strlen( jd->server ) );
+ md5_init( &jd->cached_id_prefix );
+ md5_append( &jd->cached_id_prefix, (unsigned char *) jd->username, strlen( jd->username ) );
+ md5_append( &jd->cached_id_prefix, (unsigned char *) jd->server, strlen( jd->server ) );
s = set_getstr( &jd->ic->acc->set, "resource" );
- md5_append( &id_hash, (unsigned char *) s, strlen( s ) );
- random_bytes( binbuf, 16 );
- md5_append( &id_hash, binbuf, 16 );
- md5_finish( &id_hash, binbuf );
-
- s = base64_encode( binbuf, 9 );
- jd->cached_id_prefix = g_strdup_printf( "%s%s", JABBER_CACHED_ID, s );
- g_free( s );
+ md5_append( &jd->cached_id_prefix, (unsigned char *) s, strlen( s ) );
+ random_bytes( binbuf, 4 );
+ md5_append( &jd->cached_id_prefix, binbuf, 4 );
}
static void jabber_logout( struct im_connection *ic )
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 1ff0e8dd..904bf0c4 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -85,7 +85,7 @@ struct jabber_data
struct jabber_away_state *away_state;
char *away_message;
- char *cached_id_prefix;
+ md5_state_t cached_id_prefix;
GHashTable *node_cache;
GHashTable *buddies;
};
@@ -134,10 +134,6 @@ struct jabber_chat
#define JABBER_XMLCONSOLE_HANDLE "xmlconsole"
-#define JABBER_PORT_DEFAULT "5222"
-#define JABBER_PORT_MIN 5220
-#define JABBER_PORT_MAX 5229
-
/* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the
first one should be used, but when storing a packet in the cache, a
"special" kind of ID is assigned to make it easier later to figure out
diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c
index 6e872040..1bee5009 100644
--- a/protocols/jabber/jabber_util.c
+++ b/protocols/jabber/jabber_util.c
@@ -22,6 +22,8 @@
\***************************************************************************/
#include "jabber.h"
+#include "md5.h"
+#include "base64.h"
static unsigned int next_id = 1;
@@ -133,11 +135,21 @@ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_ca
{
struct jabber_data *jd = ic->proto_data;
struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 );
- char *id;
+ md5_state_t id_hash;
+ md5_byte_t id_sum[16];
+ char *id, *asc_hash;
- id = g_strdup_printf( "%s%05x", jd->cached_id_prefix, ( next_id++ ) & 0xfffff );
+ next_id ++;
+
+ id_hash = jd->cached_id_prefix;
+ md5_append( &id_hash, (md5_byte_t*) &next_id, sizeof( next_id ) );
+ md5_finish( &id_hash, id_sum );
+ asc_hash = base64_encode( id_sum, 12 );
+
+ id = g_strdup_printf( "%s%s", JABBER_CACHED_ID, asc_hash );
xt_add_attr( node, "id", id );
g_free( id );
+ g_free( asc_hash );
entry->node = node;
entry->func = func;
@@ -183,7 +195,7 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *
char *s;
if( ( s = xt_find_attr( node, "id" ) ) == NULL ||
- strncmp( s, jd->cached_id_prefix, strlen( jd->cached_id_prefix ) ) != 0 )
+ strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 )
{
/* Silently ignore it, without an ID (or a non-cache
ID) we don't know how to handle the packet and we
@@ -195,8 +207,14 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *
if( entry == NULL )
{
+ /*
+ There's no longer an easy way to see if we generated this
+ one or someone else, and there's a ten-minute timeout anyway,
+ so meh.
+
imcb_log( ic, "Warning: Received %s-%s packet with unknown/expired ID %s!",
node->name, xt_find_attr( node, "type" ) ? : "(no type)", s );
+ */
}
else if( entry->func )
{
@@ -245,8 +263,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 )
@@ -256,8 +276,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 );
@@ -285,8 +307,13 @@ char *jabber_normalize( const char *orig )
len = strlen( orig );
new = g_new( char, len + 1 );
- for( i = 0; i < len; i ++ )
+
+ /* So it turns out the /resource part is case sensitive. Yeah, and
+ it's Unicode but feck Unicode. :-P So stop once we see a slash. */
+ for( i = 0; i < len && orig[i] != '/' ; i ++ )
new[i] = tolower( orig[i] );
+ for( ; orig[i]; i ++ )
+ new[i] = orig[i];
new[i] = 0;
return new;
@@ -329,7 +356,7 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_
for( bi = bud; bi; bi = bi->next )
{
/* Check for dupes. */
- if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
+ if( strcmp( bi->resource, s + 1 ) == 0 )
{
*s = '/';
g_free( new );
@@ -382,7 +409,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
if( ( s = strchr( jid, '/' ) ) )
{
- int none_found = 0;
+ int bare_exists = 0;
*s = 0;
if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
@@ -405,21 +432,19 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
/* See if there's an exact match. */
for( ; bud; bud = bud->next )
- if( g_strcasecmp( bud->resource, s + 1 ) == 0 )
+ if( strcmp( bud->resource, s + 1 ) == 0 )
break;
}
else
{
- /* This hack is there to make sure that O_CREAT will
- work if there's already another resouce present
- for this JID, even if it's an unknown buddy. This
- is done to handle conferences properly. */
- none_found = 1;
- /* TODO(wilmer): Find out what I was thinking when I
- wrote this??? And then fix it. This makes me sad... */
+ /* This variable tells the if down here that the bare
+ JID already exists and we should feel free to add
+ more resources, if the caller asked for that. */
+ bare_exists = 1;
}
- if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) )
+ if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
+ ( !bare_exists || imcb_find_buddy( ic, jid ) ) )
{
*s = '/';
bud = jabber_buddy_add( ic, jid );
@@ -444,7 +469,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )
/* We want an exact match, so in thise case there shouldn't be a /resource. */
return NULL;
- else if( ( bud->resource == NULL || bud->next == NULL ) )
+ else if( bud->resource == NULL || bud->next == NULL )
/* No need for selection if there's only one option. */
return bud;
else if( flags & GET_BUDDY_FIRST )
@@ -520,7 +545,9 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ )
/* If there's only one item in the list (and if the resource
matches), removing it is simple. (And the hash reference
should be removed too!) */
- if( bud->next == NULL && ( ( s == NULL || bud->resource == NULL ) || g_strcasecmp( bud->resource, s + 1 ) == 0 ) )
+ if( bud->next == NULL &&
+ ( ( s == NULL && bud->resource == NULL ) ||
+ ( bud->resource && s && strcmp( bud->resource, s + 1 ) == 0 ) ) )
{
g_hash_table_remove( jd->buddies, bud->bare_jid );
g_free( bud->bare_jid );
@@ -543,7 +570,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ )
else
{
for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next )
- if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
+ if( strcmp( bi->resource, s + 1 ) == 0 )
break;
g_free( full_jid );
diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c
index fab62a91..6cb67d42 100644
--- a/protocols/jabber/message.c
+++ b/protocols/jabber/message.c
@@ -48,6 +48,23 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */
{
GString *fullmsg = g_string_new( "" );
+
+ for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next )
+ {
+ char *ns = xt_find_attr( c, "xmlns" ), *room;
+ struct xt_node *inv, *reason;
+
+ if( strcmp( ns, XMLNS_MUC_USER ) == 0 &&
+ ( inv = xt_find_node( c->children, "invite" ) ) )
+ {
+ room = from;
+ from = xt_find_attr( inv, "from" ) ? : from;
+
+ g_string_append_printf( fullmsg, "<< \002BitlBee\002 - Invitation to chatroom %s >>\n", room );
+ if( ( reason = xt_find_node( inv->children, "reason" ) ) && reason->text_len > 0 )
+ g_string_append( fullmsg, reason->text );
+ }
+ }
if( ( s = strchr( from, '/' ) ) )
{
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/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..fe48f96d 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 )
{
@@ -177,7 +177,15 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
}
debug( "Connecting to a new switchboard with key %s", cmd[5] );
- sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW );
+
+ if( ( sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ) ) == NULL )
+ {
+ /* Although this isn't strictly fatal for the NS connection, it's
+ definitely something serious (we ran out of file descriptors?). */
+ imcb_error( ic, "Could not create new switchboard" );
+ imc_logout( ic, TRUE );
+ return( 0 );
+ }
if( md->msgq )
{
@@ -213,7 +221,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 );
@@ -269,11 +277,25 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
{
if( num_parts == 5 )
{
- md->buddycount = atoi( cmd[3] );
- md->groupcount = atoi( cmd[4] );
- if( md->groupcount > 0 )
+ int i, groupcount;
+
+ groupcount = atoi( cmd[4] );
+ if( groupcount > 0 )
+ {
+ /* valgrind says this is leaking memory, I'm guessing
+ that this happens during server redirects. */
+ if( md->grouplist )
+ {
+ for( i = 0; i < md->groupcount; i ++ )
+ g_free( md->grouplist[i] );
+ g_free( md->grouplist );
+ }
+
+ md->groupcount = groupcount;
md->grouplist = g_new0( char *, md->groupcount );
+ }
+ md->buddycount = atoi( cmd[3] );
if( !*cmd[3] || md->buddycount == 0 )
msn_logged_in( ic );
}
@@ -467,8 +489,18 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] );
- sb = msn_sb_create( ic, server, port, cmd[4], session );
- sb->who = g_strdup( cmd[5] );
+ if( ( sb = msn_sb_create( ic, server, port, cmd[4], session ) ) == NULL )
+ {
+ /* Although this isn't strictly fatal for the NS connection, it's
+ definitely something serious (we ran out of file descriptors?). */
+ imcb_error( ic, "Could not create new switchboard" );
+ imc_logout( ic, TRUE );
+ return( 0 );
+ }
+ else
+ {
+ sb->who = g_strdup( cmd[5] );
+ }
}
else if( strcmp( cmd[0], "ADD" ) == 0 )
{
@@ -646,6 +678,9 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int
{
imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders );
}
+
+ g_free( inbox );
+ g_free( folders );
}
else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 )
{
@@ -673,22 +708,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 c2966323..95d950ca 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 3caefe2b..7e14c560 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -41,13 +41,9 @@
#include "bitlbee.h"
#include "account.h"
#include "proxy.h"
+#include "query.h"
#include "md5.h"
-#define BUF_LEN MSG_LEN
-#define BUF_LONG ( BUF_LEN * 2 )
-#define MSG_LEN 2048
-#define BUF_LEN MSG_LEN
-
#define BUDDY_ALIAS_MAXLEN 388 /* because MSN names can be 387 characters */
#define WEBSITE "http://www.bitlbee.org/"
@@ -264,7 +260,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/oscar.c b/protocols/oscar/oscar.c
index 120ebc3e..28207103 100644
--- a/protocols/oscar/oscar.c
+++ b/protocols/oscar/oscar.c
@@ -60,6 +60,9 @@
#define OSCAR_GROUP "Friends"
+#define BUF_LEN 2048
+#define BUF_LONG ( BUF_LEN * 2 )
+
/* Don't know if support for UTF8 is really working. For now it's UTF16 here.
static int gaim_caps = AIM_CAPS_UTF8; */
@@ -240,6 +243,32 @@ static char *msgerrreason[] = {
};
static int msgerrreasonlen = 25;
+/* Hurray, this function is NOT thread-safe \o/ */
+static char *normalize(const char *s)
+{
+ static char buf[BUF_LEN];
+ char *t, *u;
+ int x = 0;
+
+ g_return_val_if_fail((s != NULL), NULL);
+
+ u = t = g_strdup(s);
+
+ strcpy(t, s);
+ g_strdown(t);
+
+ while (*t && (x < BUF_LEN - 1)) {
+ if (*t != ' ' && *t != '!') {
+ buf[x] = *t;
+ x++;
+ }
+ t++;
+ }
+ buf[x] = '\0';
+ g_free(u);
+ return buf;
+}
+
static gboolean oscar_callback(gpointer data, gint source,
b_input_condition condition) {
aim_conn_t *conn = (aim_conn_t *)data;
@@ -1001,13 +1030,13 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
g_hash_table_insert(od->ips, uin, (gpointer) (long) info->icqinfo.ipaddr);
}
- tmp = g_strdup(normalize(ic->acc->user));
- if (!strcmp(tmp, normalize(info->sn)))
+ if (!aim_sncmp(ic->acc->user, info->sn))
g_snprintf(ic->displayname, sizeof(ic->displayname), "%s", info->sn);
- g_free(tmp);
- imcb_buddy_status(ic, info->sn, flags, state_string, NULL);
- /* imcb_buddy_times(ic, info->sn, signon, time_idle); */
+ tmp = normalize(info->sn);
+ imcb_buddy_status(ic, tmp, flags, state_string, NULL);
+ /* imcb_buddy_times(ic, tmp, signon, time_idle); */
+
return 1;
}
@@ -1021,7 +1050,7 @@ static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) {
info = va_arg(ap, aim_userinfo_t *);
va_end(ap);
- imcb_buddy_status(ic, info->sn, 0, NULL, NULL );
+ imcb_buddy_status(ic, normalize(info->sn), 0, NULL, NULL );
return 1;
}
@@ -1077,14 +1106,14 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_
}
strip_linefeed(tmp);
- imcb_buddy_msg(ic, userinfo->sn, tmp, flags, 0);
+ imcb_buddy_msg(ic, normalize(userinfo->sn), tmp, flags, 0);
g_free(tmp);
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 +1147,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 +1163,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;
@@ -1174,7 +1205,7 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_
uin = g_strdup_printf("%u", args->uin);
message = g_strdup(args->msg);
strip_linefeed(message);
- imcb_buddy_msg(ic, uin, message, 0, 0);
+ imcb_buddy_msg(ic, normalize(uin), message, 0, 0);
g_free(uin);
g_free(message);
} break;
@@ -1193,7 +1224,7 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_
}
strip_linefeed(message);
- imcb_buddy_msg(ic, uin, message, 0, 0);
+ imcb_buddy_msg(ic, normalize(uin), message, 0, 0);
g_free(uin);
g_free(m);
g_free(message);
@@ -1468,7 +1499,7 @@ static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {
return 1;
for (i = 0; i < count; i++)
- imcb_chat_add_buddy(c->cnv, info[i].sn);
+ imcb_chat_add_buddy(c->cnv, normalize(info[i].sn));
return 1;
}
@@ -1491,7 +1522,7 @@ static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {
return 1;
for (i = 0; i < count; i++)
- imcb_chat_remove_buddy(c->cnv, info[i].sn, NULL);
+ imcb_chat_remove_buddy(c->cnv, normalize(info[i].sn), NULL);
return 1;
}
@@ -1542,7 +1573,7 @@ static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {
tmp = g_malloc(BUF_LONG);
g_snprintf(tmp, BUF_LONG, "%s", msg);
- imcb_chat_msg(ccon->cnv, info->sn, tmp, 0, 0);
+ imcb_chat_msg(ccon->cnv, normalize(info->sn), tmp, 0, 0);
g_free(tmp);
return 1;
@@ -1755,7 +1786,7 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) {
time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
g_snprintf(sender, sizeof(sender), "%u", msg->sender);
strip_linefeed(dialog_msg);
- imcb_buddy_msg(ic, sender, dialog_msg, 0, t);
+ imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t);
g_free(dialog_msg);
} break;
@@ -1776,7 +1807,7 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) {
}
strip_linefeed(dialog_msg);
- imcb_buddy_msg(ic, sender, dialog_msg, 0, t);
+ imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t);
g_free(dialog_msg);
g_free(m);
} break;
@@ -2014,23 +2045,26 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
struct im_connection *ic = sess->aux_data;
struct aim_ssi_item *curitem;
int tmp;
+ char *nrm;
/* Add from server list to local list */
tmp = 0;
for (curitem=sess->ssi.items; curitem; curitem=curitem->next) {
+ nrm = curitem->name ? normalize(curitem->name) : NULL;
+
switch (curitem->type) {
case 0x0000: /* Buddy */
- if ((curitem->name) && (!imcb_find_buddy(ic, curitem->name))) {
+ if ((curitem->name) && (!imcb_find_buddy(ic, nrm))) {
char *realname = NULL;
if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1))
realname = aim_gettlv_str(curitem->data, 0x0131, 1);
- imcb_add_buddy(ic, curitem->name, NULL);
+ imcb_add_buddy(ic, nrm, NULL);
if (realname) {
- imcb_buddy_nick_hint(ic, curitem->name, realname);
- imcb_rename_buddy(ic, curitem->name, realname);
+ imcb_buddy_nick_hint(ic, nrm, realname);
+ imcb_rename_buddy(ic, nrm, realname);
g_free(realname);
}
}
@@ -2042,7 +2076,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
for (list=ic->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
if (!list) {
char *name;
- name = g_strdup(normalize(curitem->name));
+ name = g_strdup(nrm);
ic->permit = g_slist_append(ic->permit, name);
tmp++;
}
@@ -2055,7 +2089,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
for (list=ic->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
if (!list) {
char *name;
- name = g_strdup(normalize(curitem->name));
+ name = g_strdup(nrm);
ic->deny = g_slist_append(ic->deny, name);
tmp++;
}
@@ -2117,7 +2151,7 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... )
st = aimbs_get16( &fr->data );
if( st == 0x00 )
{
- imcb_add_buddy( sess->aux_data, list, NULL );
+ imcb_add_buddy( sess->aux_data, normalize(list), NULL );
}
else if( st == 0x0E )
{
@@ -2447,15 +2481,15 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...)
if(type2 == 0x0002) {
/* User is typing */
- imcb_buddy_typing(ic, sn, OPT_TYPING);
+ imcb_buddy_typing(ic, normalize(sn), OPT_TYPING);
}
else if (type2 == 0x0001) {
/* User has typed something, but is not actively typing (stale) */
- imcb_buddy_typing(ic, sn, OPT_THINKING);
+ imcb_buddy_typing(ic, normalize(sn), OPT_THINKING);
}
else {
/* User has stopped typing */
- imcb_buddy_typing(ic, sn, 0);
+ imcb_buddy_typing(ic, normalize(sn), 0);
}
return 1;
@@ -2587,15 +2621,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/libyahoo2.c b/protocols/yahoo/libyahoo2.c
index ce38bc73..a61955c4 100644
--- a/protocols/yahoo/libyahoo2.c
+++ b/protocols/yahoo/libyahoo2.c
@@ -68,8 +68,6 @@ char *strchr (), *strrchr ();
#ifdef __MINGW32__
# include <winsock2.h>
-# define write(a,b,c) send(a,b,c,0)
-# define read(a,b,c) recv(a,b,c,0)
#endif
#include <stdlib.h>
@@ -380,7 +378,6 @@ static void del_from_list(struct yahoo_data *yd)
}
/* call repeatedly to get the next one */
-/*
static struct yahoo_input_data * find_input_by_id(int id)
{
YList *l;
@@ -391,7 +388,6 @@ static struct yahoo_input_data * find_input_by_id(int id)
}
return NULL;
}
-*/
static struct yahoo_input_data * find_input_by_id_and_webcam_user(int id, const char * who)
{
@@ -736,7 +732,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);
@@ -796,6 +792,7 @@ static int yahoo_send_data(int fd, void *data, int len)
void yahoo_close(int id)
{
struct yahoo_data *yd = find_conn_by_id(id);
+
if(!yd)
return;
@@ -3165,7 +3162,7 @@ int yahoo_write_ready(int id, int fd, void *data)
struct data_queue *tx;
LOG(("write callback: id=%d fd=%d data=%p", id, fd, data));
- if(!yid || !yid->txqueues)
+ if(!yid || !yid->txqueues || !find_conn_by_id(id))
return -2;
tx = yid->txqueues->data;
@@ -3350,7 +3347,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;
@@ -3841,11 +3838,9 @@ void yahoo_logoff(int id)
}
}
-
-/* do {
+ do {
yahoo_input_close(yid);
- } while((yid = find_input_by_id(id)));*/
-
+ } while((yid = find_input_by_id(id)));
}
void yahoo_get_list(int id)
diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c
index 52747bb4..0db6e27a 100644
--- a/protocols/yahoo/yahoo.c
+++ b/protocols/yahoo/yahoo.c
@@ -162,10 +162,7 @@ static void byahoo_logout( struct im_connection *ic )
}
g_slist_free( yd->buddygroups );
- if( yd->logged_in )
- yahoo_logoff( yd->y2_id );
- else
- yahoo_close( yd->y2_id );
+ yahoo_logoff( yd->y2_id );
g_free( yd );
}
@@ -314,7 +311,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 )
@@ -454,10 +451,6 @@ gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condit
{
struct byahoo_write_ready_data *d = data;
- if( !byahoo_get_ic_by_id( d->id ) )
- /* WTF doesn't libyahoo clean this up? */
- return FALSE;
-
yahoo_write_ready( d->id, d->fd, d->data );
return FALSE;
@@ -797,16 +790,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 );
diff --git a/protocols/yahoo/yahoo_httplib.c b/protocols/yahoo/yahoo_httplib.c
index dbbe2a84..1b084992 100644
--- a/protocols/yahoo/yahoo_httplib.c
+++ b/protocols/yahoo/yahoo_httplib.c
@@ -50,8 +50,6 @@ char *strchr (), *strrchr ();
#include "yahoo_debug.h"
#ifdef __MINGW32__
# include <winsock2.h>
-# define write(a,b,c) send(a,b,c,0)
-# define read(a,b,c) recv(a,b,c,0)
# define snprintf _snprintf
#endif