summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot2006-06-16 01:03:02 -0500
committerroot2006-06-16 01:03:02 -0500
commit9a45660a93d38dfb4f151ac9c26d225c47d51e84 (patch)
tree099d0ad069e9445e673747c40ed9844111b856d2
parent3a476e122f9a90a9b14e2d70d3633cd7f37165a0 (diff)
./chat-irc/bitlbee/msn.patch: 2006/06/15 sync stable from p4
-rw-r--r--chat-irc/bitlbee/msn.patch2408
1 files changed, 0 insertions, 2408 deletions
diff --git a/chat-irc/bitlbee/msn.patch b/chat-irc/bitlbee/msn.patch
deleted file mode 100644
index 7f429b4f8a..0000000000
--- a/chat-irc/bitlbee/msn.patch
+++ /dev/null
@@ -1,2408 +0,0 @@
-diff -urN bitlbee-0.92/commands.c bitlbee-0.92.akke/commands.c
---- bitlbee-0.92/commands.c 2005-02-08 22:48:35.000000000 +0100
-+++ bitlbee-0.92.akke/commands.c 2005-05-07 02:29:45.000000000 +0200
-@@ -642,6 +642,33 @@
- return( 0 );
- }
-
-+int user_is_blocked( user_t *u )
-+{
-+ char *buf;
-+ struct gaim_connection *gc = u->gc;
-+ GSList *l;
-+ int length = strlen( u->user ) + 1 /* @ */ + strlen( u->host ) + 1 /* trailing \x00 */;
-+
-+ buf = g_new0( char, length + 1 );
-+ if ( !buf )
-+ return( 0 );
-+
-+ g_snprintf( buf, length, "%s@%s", u->user, u->host );
-+
-+ for( l = gc->deny; l; l = l->next )
-+ if( g_strcasecmp( l->data, buf ) == 0 )
-+ return( 1 );
-+
-+ return( 0 );
-+}
-+
-+char *blocked_string( user_t *u )
-+{
-+ if ( user_is_blocked( u ) )
-+ return " (User is blocked!)";
-+ return "";
-+}
-+
- int cmd_blist( irc_t *irc, char **cmd )
- {
- int online = 0, away = 0, offline = 0;
-@@ -665,21 +692,21 @@
- if( online == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && !u->away )
- {
- g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, proto_name[u->gc->user->protocol] );
-- irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Online" );
-+ irc_usermsg( irc, "%-16.16s %-40.40s %s%s", u->nick, s, "Online", blocked_string( u ) );
- n_online ++;
- }
-
- if( away == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && u->away )
- {
- g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, proto_name[u->gc->user->protocol] );
-- irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, u->away );
-+ irc_usermsg( irc, "%-16.16s %-40.40s %s%s", u->nick, s, u->away, blocked_string( u ) );
- n_away ++;
- }
-
- if( offline == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && !u->online )
- {
- g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, proto_name[u->gc->user->protocol] );
-- irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Offline" );
-+ irc_usermsg( irc, "%-16.16s %-40.40s %s%s", u->nick, s, "Offline", blocked_string( u ) );
- n_offline ++;
- }
-
-diff -urN bitlbee-0.92/irc.c bitlbee-0.92.akke/irc.c
---- bitlbee-0.92/irc.c 2005-02-24 00:32:02.000000000 +0100
-+++ bitlbee-0.92.akke/irc.c 2005-05-07 03:15:20.000000000 +0200
-@@ -31,6 +31,43 @@
-
- GSList *irc_connection_list = NULL;
-
-+char *set_update_mymsnbuddyimage( irc_t *irc, set_t *set, char *value )
-+{
-+ GSList *c = get_connections();
-+ struct gaim_connection *conn;
-+
-+ if( access( value, R_OK ) == 0 ) /* buddy-image is readable ... */
-+ {
-+ if( set->value ) /* stupid hack, but required: */
-+ { /* We need the value before this function ends */
-+ g_free( set->value ); /* as we call set_getstr() from the msn module */
-+ } /* when status is changed. And we do that here! */
-+ /* I don't think there's an easier method to */
-+ set->value = g_strdup( value ); /* trigger a call to a function when a 'set' is */
-+ /* done on my_buddy_image */
-+
-+ while( c )
-+ {
-+ conn = ( struct gaim_connection * ) c->data; /* We set the away state to the current away state */
-+ if( conn->protocol == PROTO_MSN ) /* This is how MSN resets it's msnobject so users know */
-+ { /* his buddy-image has changed... */
-+ if( conn->flags & OPT_LOGGED_IN ) /* Not a real 'hack' here.. it's just microsoft's */
-+ proto_away( conn, conn->away ); /* default... lol */
-+ }
-+
-+ c = c->next;
-+ }
-+ }
-+ else /* buddy-image is not readable ... */
-+ {
-+ irc_usermsg( irc, "Could not read file '%s'. Keeping current buddy_image...", value);
-+ return NULL;
-+ }
-+
-+ return( value );
-+}
-+
-+
- irc_t *irc_new( int fd )
- {
- irc_t *irc = g_new0( irc_t, 1 );
-@@ -128,7 +165,27 @@
- set_add( irc, "save_on_quit", "1", set_eval_bool );
- set_add( irc, "to_char", ": ", set_eval_to_char );
- set_add( irc, "typing_notice", "false", set_eval_bool );
--
-+
-+ /* MSN buddy/emoticon images stuff */
-+ set_add( irc, "msn_images_path_buddy", "/tmp/msn", NULL );
-+ set_add( irc, "msn_images_path_emoticon", "/tmp/msn", NULL );
-+ set_add( irc, "msn_images_mybuddyimage", "/tmp/msn/myimage.png", set_update_mymsnbuddyimage );
-+ /* MSN buddy list stuff */
-+ set_add( irc, "msn_buddylist_checks", "true", set_eval_bool );
-+ /* MSN notify stuff */
-+ set_add( irc, "msn_notify_openwindow", "true", set_eval_bool );
-+ set_add( irc, "msn_notify_closewindow", "true", set_eval_bool );
-+ set_add( irc, "msn_notify_timeout", "true", set_eval_bool );
-+ /* MSN font stuff */
-+ set_add( irc, "msn_font_face", "MS Shell Dlg", NULL );
-+ set_add( irc, "msn_font_CS", "0", set_eval_int );
-+ set_add( irc, "msn_font_PF", "22", set_eval_int );
-+ set_add( irc, "msn_font_color", "000000", NULL );
-+ set_add( irc, "msn_font_bold", "false", set_eval_bool );
-+ set_add( irc, "msn_font_italic", "false", set_eval_bool );
-+ set_add( irc, "msn_font_overstrike", "false", set_eval_bool );
-+ set_add( irc, "msn_font_underline", "false", set_eval_bool );
-+
- conf_loaddefaults( irc );
-
- return( irc );
-diff -urN bitlbee-0.92/protocols/msn/Makefile bitlbee-0.92.akke/protocols/msn/Makefile
---- bitlbee-0.92/protocols/msn/Makefile 2004-04-08 18:34:11.000000000 +0200
-+++ bitlbee-0.92.akke/protocols/msn/Makefile 2005-05-07 02:30:02.000000000 +0200
-@@ -9,7 +9,7 @@
- -include ../../Makefile.settings
-
- # [SH] Program variables
--objects = msn.o msn_util.o ns.o passport.o sb.o tables.o
-+objects = msn.o msn_util.o ns.o passport.o sb.o tables.o msnobject.o msnc1.o
-
- CFLAGS += -Wall
- LFLAGS += -r
-diff -urN bitlbee-0.92/protocols/msn/msn.c bitlbee-0.92.akke/protocols/msn/msn.c
---- bitlbee-0.92/protocols/msn/msn.c 2005-02-23 18:31:49.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/msn.c 2005-05-07 03:15:12.000000000 +0200
-@@ -25,6 +25,8 @@
-
- #include "nogaim.h"
- #include "msn.h"
-+#include "msnc1.h"
-+#include "msnobject.h"
-
- static struct prpl *my_protocol = NULL;
-
-@@ -57,6 +59,9 @@
- md->away_state = msn_away_state_list;
-
- msn_connections = g_slist_append( msn_connections, gc );
-+
-+ p2p_init_random();
-+ md->msnobject = NULL;
- }
- }
-
-@@ -77,6 +82,11 @@
-
- while( md->switchboards )
- msn_sb_destroy( md->switchboards->data );
-+
-+ msn_cleanup_userinfolist( md );
-+ if( md->msnobject )
-+ g_free( md->msnobject );
-+
-
- if( md->msgq )
- {
-@@ -200,7 +210,15 @@
- if( !st ) st = msn_away_state_list;
- md->away_state = st;
-
-- g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, st->code );
-+ msn_update_mybuddyimage(gc);
-+ if (md->msnobject)
-+ {
-+ g_snprintf( buf, sizeof( buf ), "CHG %d %s %s %s\r\n", ++md->trId, st->code, CLIENT_ID, md->msnobject );
-+ }
-+ else
-+ {
-+ g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, st->code, 0 );
-+ }
- msn_write( gc, buf, strlen( buf ) );
- }
-
-@@ -241,7 +259,35 @@
- static void msn_get_info(struct gaim_connection *gc, char *who)
- {
- /* Just make an URL and let the user fetch the info */
-- serv_got_crap( gc, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who );
-+ struct msn_data *md = gc->proto_data;
-+ struct msn_userinfo *userinfo = msn_find_userinfo( md, who );
-+ if ( userinfo )
-+ {
-+ char *filename = msn_imagefullpath( gc, userinfo->who, userinfo->msnobject, TYPE_BUDDY_IMAGE, NULL, "png" );
-+ if( filename )
-+ {
-+ if( access( filename, F_OK ) == 0 )
-+ {
-+ serv_got_crap( gc, "%s\n%s: %s%s\n - buddy-image: %s",
-+ _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who, filename);
-+ }
-+ else
-+ {
-+ serv_got_crap( gc, "%s\n%s: %s%s\n - buddy-image would be %s, but it's not downloaded yet! :(",
-+ _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who, filename);
-+ }
-+ }
-+ else
-+ {
-+ serv_got_crap( gc, "%s\n%s: %s%s\n - Could not converg msnobject to filename, msnobject: %s",
-+ _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who, userinfo->msnobject);
-+ }
-+ }
-+ else
-+ {
-+ serv_got_crap( gc, "%s\n%s: %s%s\n - He hasn't got a buddy-image!",
-+ _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who );
-+ }
- }
-
- static void msn_add_buddy( struct gaim_connection *gc, char *who )
-diff -urN bitlbee-0.92/protocols/msn/msn.h bitlbee-0.92.akke/protocols/msn/msn.h
---- bitlbee-0.92/protocols/msn/msn.h 2004-12-03 22:59:08.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/msn.h 2005-05-07 02:38:45.000000000 +0200
-@@ -28,6 +28,8 @@
- #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"
-
-+#define CLIENT_ID "268435500"
-+
- #ifdef _WIN32
- #define debug
- #else
-@@ -44,7 +46,7 @@
- #define MSN_MESSAGE_HEADERS "MIME-Version: 1.0\r\n" \
- "Content-Type: text/plain; charset=UTF-8\r\n" \
- "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \
-- "X-MMS-IM-Format: FN=MS%20Shell%20Dlg; EF=; CO=0; CS=0; PF=0\r\n" \
-+ "X-MMS-IM-Format: FN=%s; EF=%s; CO=%s; CS=%d; PF=%d\r\n" \
- "\r\n"
-
- #define MSN_TYPING_HEADERS "MIME-Version: 1.0\r\n" \
-@@ -55,6 +57,13 @@
-
- #define PROFILE_URL "http://members.msn.com/"
-
-+struct msn_userinfo
-+{
-+ char *who;
-+ char *msnobject;
-+};
-+
-+
- struct msn_data
- {
- struct gaim_connection *gc;
-@@ -68,6 +77,10 @@
- GSList *switchboards;
- int buddycount;
- struct msn_away_state *away_state;
-+
-+ /* P2P stuff */
-+ char *msnobject;
-+ GSList *userinfolist;
- };
-
- struct msn_switchboard
-@@ -87,6 +100,9 @@
- GSList *msgq;
- char *who;
- struct conversation *chat;
-+
-+ /* P2P stuff*/
-+ GSList *p2p_sessionlist;
- };
-
- struct msn_away_state
-diff -urN bitlbee-0.92/protocols/msn/msn_util.c bitlbee-0.92.akke/protocols/msn/msn_util.c
---- bitlbee-0.92/protocols/msn/msn_util.c 2004-05-03 22:02:52.000000000 +0200
-+++ bitlbee-0.92.akke/protocols/msn/msn_util.c 2005-05-07 03:15:25.000000000 +0200
-@@ -26,6 +26,8 @@
- #include "nogaim.h"
- #include "msn.h"
- #include <ctype.h>
-+#include "msnobject.h"
-+#include "msnc1.h"
-
- int msn_write( struct gaim_connection *gc, char *s, int len )
- {
-@@ -54,7 +56,15 @@
- execute this code if we're not away. */
- if( md->away_state == msn_away_state_list )
- {
-- g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 );
-+ msn_update_mybuddyimage(gc);
-+ if ( md->msnobject )
-+ {
-+ g_snprintf( buf, sizeof( buf ), "CHG %d %s %s %s\r\n", ++md->trId, md->away_state->code, CLIENT_ID, md->msnobject );
-+ }
-+ else
-+ {
-+ g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 );
-+ }
- return( msn_write( gc, buf, strlen( buf ) ) );
- }
-
-@@ -318,7 +328,13 @@
- if( h->msglen > h->rxlen )
- break;
-
-- msg = g_strndup( h->rxq, h->msglen );
-+ /* maybe some info is required, why did this buddy-image patch
-+ * replace g_strndup() with g_memdup()?
-+ * Well, easy:
-+ * g_strndup() doesn't like binary data, g_memdup() does! */
-+ msg = g_memdup( h->rxq, h->msglen + 1 );
-+ msg[h->msglen]=0;
-+
- cmd = msn_linesplit( h->cmd_text );
- for( count = 0; cmd[count]; count ++ );
-
-diff -urN bitlbee-0.92/protocols/msn/msnc1.c bitlbee-0.92.akke/protocols/msn/msnc1.c
---- bitlbee-0.92/protocols/msn/msnc1.c 1970-01-01 01:00:00.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/msnc1.c 2005-05-07 03:10:01.000000000 +0200
-@@ -0,0 +1,1387 @@
-+/*
-+ * Implementation of the buddy/emoticon - images introduced in MSN6
-+ * -----------------------------------------------------------------
-+ *
-+ * This is a rather quick-implementation and could probably be
-+ * optimized/corrected in many ways. But I don't even like MSN!
-+ * I just implemented this because ppl kept asking why I didn't
-+ * configure a buddy-image (they don't know what bitlbee is!).
-+ *
-+ * So I decided to implement this stupid feature into bitlbee but
-+ * I don't realy care about if the code is good or bad. The good
-+ * thing is it's working and now ppl can see my face in their MSN
-+ * window... And I can see theirs, but like I said, I don't care :p
-+ *
-+ * Enjoy!
-+ *
-+ * Andy Knuts (irc://akke && email://djfred@poeperkesdag.be)
-+ *
-+ */
-+
-+#include "nogaim.h"
-+#include "msn.h"
-+#include "msnc1.h"
-+#include "msnobject.h"
-+
-+/*
-+ * Sets your buddy image to the one specified in the my_buddy_image
-+ * setting.
-+ */
-+void msn_update_mybuddyimage( struct gaim_connection *gc )
-+{
-+ struct msn_data *md = gc->proto_data;
-+ char *filename = set_getstr( gc->irc, "msn_images_mybuddyimage" );
-+
-+ if ( filename && access( filename, R_OK ) == 0 )
-+ {
-+ if( md->msnobject )
-+ g_free( md->msnobject );
-+
-+ md->msnobject = msnobject_from_params( gc->username, TYPE_BUDDY_IMAGE, filename );
-+ }
-+ else
-+ {
-+ do_error_dialog(gc, "Could not create msnobject for my buddy image. Please check your 'my_buddy_image' setting!", "MSN");
-+ }
-+}
-+
-+/*
-+ * returns the userinfo ( containing msnobject etc... ) for a given user
-+ */
-+struct msn_userinfo *msn_find_userinfo( struct msn_data *md, char *who )
-+{
-+ GSList *tmp = md->userinfolist;
-+
-+ struct msn_userinfo *userinfo;
-+
-+ while( tmp != NULL )
-+ {
-+ userinfo = ( struct msn_userinfo * ) tmp->data;
-+ if( !strcmp( userinfo->who, who ) )
-+ return userinfo;
-+
-+ tmp = g_slist_next( tmp );
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * deletes all data from a msn_userinfo struct
-+ */
-+void msn_cleanup_userinfo( struct msn_userinfo *userinfo )
-+{
-+ if( userinfo->who )
-+ {
-+ g_free( userinfo->who );
-+ userinfo->who = NULL;
-+ }
-+
-+ if( userinfo->msnobject )
-+ {
-+ g_free( userinfo->msnobject );
-+ userinfo->msnobject = NULL;
-+ }
-+}
-+
-+/*
-+ * deleted all userinfo data from a msn_data struct
-+ */
-+void msn_cleanup_userinfolist( struct msn_data *md )
-+{
-+ GSList *tmp = md->userinfolist;
-+ if( tmp )
-+ {
-+ while( tmp != NULL )
-+ {
-+ msn_cleanup_userinfo(( struct msn_userinfo* )tmp->data );
-+ tmp = g_slist_next( tmp );
-+ }
-+
-+ g_slist_free( md->userinfolist );
-+ md->userinfolist = NULL;
-+ }
-+}
-+
-+/*
-+ * add or update an existing userinfo in md->userinfolist GSList
-+ */
-+void msn_add_or_update_userinfolist( struct gaim_connection *gc, struct msn_userinfo *new_userinfo )
-+{
-+ struct msn_userinfo *userinfo;
-+ struct msn_data *md = gc->proto_data;
-+ userinfo = msn_find_userinfo( md, new_userinfo->who );
-+ int user_buddyimage_changed = 0;
-+ if( userinfo )
-+ {
-+ if( userinfo->msnobject && new_userinfo->msnobject &&
-+ strcmp(userinfo->msnobject, new_userinfo->msnobject) != 0 )
-+ {
-+ user_buddyimage_changed = 1;
-+ }
-+ msn_cleanup_userinfo( userinfo );
-+ md->userinfolist = g_slist_remove( md->userinfolist, userinfo );
-+ }
-+ md->userinfolist = g_slist_append( md->userinfolist, new_userinfo );
-+ if( user_buddyimage_changed )
-+ {
-+ struct msn_switchboard *sb = msn_sb_by_handle( gc, new_userinfo->who );
-+ if( sb )
-+ {
-+ p2p_request_msnobject(sb, sb->who, NULL, NULL );
-+ }
-+ }
-+}
-+
-+/*
-+ * create a userinfo struct from the provided parameters
-+ */
-+
-+struct msn_userinfo *userinfo_from_params( char *who, char *msnobject )
-+{
-+ struct msn_userinfo *userinfo;
-+ userinfo = g_new( struct msn_userinfo, 1 );
-+
-+ if( !userinfo )
-+ return NULL;
-+
-+ userinfo->who = g_strdup( who );
-+ userinfo->msnobject = g_strdup( msnobject );
-+
-+ return userinfo;
-+}
-+
-+
-+/*
-+ * 2 stupid functions actually ...
-+ */
-+void p2p_init_random()
-+{
-+ srand( time( NULL ) );
-+}
-+
-+DWORD p2p_randomnr()
-+{
-+ return rand();
-+}
-+
-+/*
-+ * generate a random UID
-+ */
-+char *p2p_rand_guid()
-+{
-+ return g_strdup_printf( "%4X%4X-%4X-%4X-%4X-%4X%4X%4X",
-+ rand() % 0xAAFF + 0x1111, rand() % 0xAAFF + 0x1111,
-+ rand() % 0xAAFF + 0x1111, rand() % 0xAAFF + 0x1111,
-+ rand() % 0xAAFF + 0x1111, rand() % 0xAAFF + 0x1111,
-+ rand() % 0xAAFF + 0x1111, rand() % 0xAAFF + 0x1111 );
-+}
-+
-+/*
-+ * create a P2PPacket and initialize it's members to the defauls...
-+ */
-+struct P2PPacket *p2p_packet_new()
-+{
-+ struct P2PPacket *packet = g_new0( struct P2PPacket, 1 );
-+
-+ if( !packet )
-+ return NULL;
-+
-+/*
-+ packet->destination = NULL;
-+ packet->filename = NULL;
-+ packet->call_id = NULL;
-+ packet->branch = NULL;
-+*/
-+ packet->fd = -1;
-+
-+ return packet;
-+}
-+
-+/*
-+ * convert a textbuffer containing a packet into a packet struct
-+ * ... returns NULL on error
-+ */
-+struct P2PPacket *p2p_packet_from_buffer( char *buffer, int length )
-+{
-+ int pos;
-+ struct P2PPacket *packet;
-+
-+ if( length <( sizeof( struct P2PHeader ) + sizeof( struct P2PFooter ) ) )
-+ return NULL;
-+
-+ packet = p2p_packet_new();
-+ if( !packet )
-+ return NULL;
-+
-+ pos = 0;
-+
-+ memcpy( &( packet->header ), buffer, sizeof( struct P2PHeader ) );
-+ pos += sizeof( struct P2PHeader );
-+
-+ if( length < ( sizeof( struct P2PHeader ) + packet->header.length + sizeof( struct P2PFooter ) ) )
-+ {
-+ g_free( packet );
-+ return NULL;
-+ }
-+
-+ if( packet->header.length > 0 )
-+ {
-+ memcpy( packet->data, buffer+pos, packet->header.length );
-+ pos += packet->header.length;
-+ }
-+
-+ memcpy( &( packet->footer ), buffer+pos, sizeof( struct P2PFooter ) );
-+
-+ return packet;
-+}
-+
-+/*
-+ * find p2p packet by call_id
-+ */
-+struct P2PPacket *p2p_find_packet_by_callid( struct msn_switchboard *sb, char *call_id )
-+{
-+ if( !call_id )
-+ return NULL;
-+
-+ GSList *tmp = sb->p2p_sessionlist;
-+
-+ struct P2PPacket *packet;
-+
-+ while( tmp != NULL )
-+ {
-+ packet = ( struct P2PPacket * ) tmp->data;
-+ if( packet->call_id &&
-+ !strcmp( packet->call_id, call_id ) )
-+ return packet;
-+
-+ tmp = g_slist_next( tmp );
-+ }
-+
-+ return NULL;
-+
-+}
-+
-+/*
-+ * find a session by type/value in the current session list of this sb
-+ */
-+struct P2PPacket *p2p_find_packet( struct msn_switchboard *sb, DWORD value, int type )
-+{
-+ GSList *tmp = sb->p2p_sessionlist;
-+ struct P2PPacket *packet;
-+
-+ if( value == 0 )
-+ return NULL;
-+
-+ while( tmp != NULL )
-+ {
-+ packet = ( struct P2PPacket * ) tmp->data;
-+ switch( type )
-+ {
-+ case FIND_BY_SESSION_ID:
-+ if( packet->header.session_id == value )
-+ {
-+ return packet;
-+ }
-+ break;
-+
-+ case FIND_BY_ID:
-+ if( packet->header.id == value )
-+ {
-+ return packet;
-+ }
-+ break;
-+
-+ default:
-+ return NULL;
-+ }
-+
-+ tmp = g_slist_next( tmp );
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * extracts the given header from the packet slp data by doing
-+ * it's utmost best to find it!
-+ */
-+char *p2p_findheader( struct P2PPacket *packet, char *header )
-+{
-+ char *p, *tmp;
-+
-+ p = msn_findheader( packet->data, header, packet->header.length );
-+
-+ if( p )
-+ return p;
-+
-+ tmp = strstr( packet->data, "\r\n\r\n" );
-+ while( tmp )
-+ {
-+ tmp += 4;
-+
-+ p = msn_findheader( tmp, header, packet->header.length - ( tmp - packet->data ) );
-+
-+ if( p )
-+ return p;
-+
-+ tmp = strstr( tmp, "\r\n\r\n" );
-+ }
-+
-+ tmp = strstr( packet->data, header );
-+
-+ if( tmp )
-+ {
-+ char *tmp2;
-+ tmp2 = strstr( tmp, "\r" );
-+ if( tmp2 )
-+ {
-+ tmp += strlen( header );
-+ int length = ( tmp2-tmp );
-+ p = g_new0( char, length+1 );
-+ if( !p )
-+ return NULL;
-+ strncpy( p, tmp, length );
-+ p[length]=0;
-+ return p;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * free all properties of a P2PPacket
-+ */
-+void p2p_cleanup_packet( struct P2PPacket *packet )
-+{
-+ if( packet->destination )
-+ {
-+ g_free( packet->destination );
-+ packet->destination = NULL;
-+ }
-+
-+ if( packet->branch )
-+ {
-+ g_free( packet->branch );
-+ packet->branch = NULL;
-+ }
-+
-+ if( packet->call_id )
-+ {
-+ g_free( packet->call_id );
-+ packet->call_id = NULL;
-+ }
-+
-+ if( packet->filename )
-+ {
-+ g_free( packet->filename );
-+ packet->filename = NULL;
-+ }
-+
-+ if( packet->fd != -1 )
-+ {
-+ close( packet->fd );
-+ packet->fd = -1;
-+ }
-+}
-+
-+/*
-+ * gets called from sb.c every time before the sb itself gets g_free()'s
-+ */
-+void p2p_cleanup_sb( struct msn_switchboard *sb )
-+{
-+ GSList *tmp;
-+
-+ tmp = sb->p2p_sessionlist;
-+
-+ if( tmp )
-+ {
-+ while( tmp != NULL )
-+ {
-+ p2p_cleanup_packet(( struct P2PPacket * )tmp->data );
-+ tmp = g_slist_next( tmp );
-+ }
-+
-+ g_slist_free( sb->p2p_sessionlist );
-+ sb->p2p_sessionlist = NULL;
-+ }
-+}
-+
-+/*
-+ * returns a fullpath for the requested image
-+ */
-+char *msn_imagefullpath( struct gaim_connection *gc, char *who, char *msnobject, int type, char *emoticon_shortcut, char *ext )
-+{
-+ char *path = NULL, *fullpath = NULL, *sha1c, *sha1d, md5[60], filename[150];
-+ struct stat statinfo;
-+ int buffersize;
-+ md5_state_t state;
-+ md5_byte_t digest[16];
-+ user_t *user;
-+ int i;
-+
-+ switch( type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ path = set_getstr( gc->irc, "msn_images_path_buddy" );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ path = set_getstr( gc->irc, "msn_images_path_emoticon" );
-+ break;
-+ }
-+
-+ if( !path )
-+ return NULL;
-+
-+ if(( stat( path, &statinfo ) ) != 0 )
-+ return NULL;
-+
-+ if( !S_ISDIR( statinfo.st_mode ) )
-+ return NULL;
-+
-+ sha1c = msnobject_get_field( "SHA1C", msnobject );
-+ if( !sha1c )
-+ {
-+ do_error_dialog( gc, "Could not allocate memory for 'sha1c' in msn_imagefullpath()", "MSN" );
-+ return NULL;
-+ }
-+
-+ sha1d = msnobject_get_field( "SHA1D", msnobject );
-+ if( !sha1d )
-+ {
-+ do_error_dialog( gc, "Could not allocate memory for 'sha1d' in msn_imagefullpath()", "MSN" );
-+ g_free( sha1c );
-+ return NULL;
-+ }
-+
-+ md5_init( &state );
-+ md5_append( &state,( const md5_byte_t * ) sha1c, strlen( sha1c ) );
-+ md5_append( &state,( const md5_byte_t * ) sha1d, strlen( sha1d ) );
-+ md5_finish( &state, digest );
-+
-+ g_free( sha1c );
-+ g_free( sha1d );
-+
-+ bzero( md5, sizeof( md5 ) );
-+
-+ for( i = 0; i < 16; i ++ )
-+ g_snprintf( md5+strlen( md5 ), 3, "%02x", digest[i] );
-+
-+ g_snprintf( filename, sizeof( filename ), "%s.%s", md5, ext );
-+
-+ user = user_findhandle( gc, who );
-+ if ( user )
-+ {
-+ buffersize = strlen( path ) + 1 + strlen( who ) + 1 + strlen( filename );
-+
-+ if( emoticon_shortcut )
-+ buffersize += strlen( emoticon_shortcut );
-+
-+ fullpath = g_new0( char, buffersize );
-+
-+ if ( fullpath )
-+ {
-+ switch( type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ g_snprintf( fullpath, buffersize, "%s/%s.%s", path, user->nick, filename );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ g_snprintf( fullpath, buffersize, "%s/%s.emoticon.%s", path, user->nick, filename );
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ do_error_dialog( gc, "Could not allocate memory for 'fullpath' in msn_imagefullpath()", "MSN" );
-+ }
-+ }
-+ else
-+ {
-+ do_error_dialog( gc, "Could not find userhandle in msn_imagefullpath()", "MSN" );
-+ }
-+
-+ return fullpath;
-+}
-+
-+
-+/*
-+ * send packet 'packet' to the sb
-+ */
-+void p2p_sendpacket( struct msn_switchboard *sb, struct P2PPacket *packet )
-+{
-+
-+ struct gaim_connection *gc = sb->gc;
-+ char cmd[1024], *buffer, *p;
-+ char *header;
-+ int len;
-+
-+ if( !packet->destination )
-+ {
-+ do_error_dialog( gc, "Could not send packet in p2p_sendpacket(), no destination givven!", "MSN" );
-+ return;
-+ }
-+
-+ header = "MIME-Version: 1.0\r\nContent-Type: application/x-msnmsgrp2p\r\nP2P-Dest: ";
-+
-+ len = strlen( header ) +
-+ strlen( packet->destination ) +
-+ 4 /* \r\n\r\n */ +
-+ sizeof( struct P2PHeader ) +
-+ sizeof( struct P2PFooter );
-+
-+ if( packet->header.length > 0 )
-+ len += packet->header.length; /* length of packet->data */
-+
-+ buffer = g_new0(char, len + 1);
-+
-+ if (!buffer)
-+ {
-+ do_error_dialog( gc, "Could not allocate memory for 'buffer' in p2p_sendpacket()", "MSN" );
-+ return;
-+ }
-+
-+ g_snprintf( buffer, len, "%s%s\r\n\r\n", header, packet->destination );
-+ p = buffer+strlen( buffer );
-+
-+ memcpy( p, &( packet->header ), sizeof( struct P2PHeader ) );
-+ p += sizeof( struct P2PHeader );
-+
-+ if( packet->header.length > 0 )
-+ {
-+ memcpy( p, packet->data, packet->header.length );
-+ p += packet->header.length;
-+ }
-+
-+ memcpy( p, &( packet->footer ), sizeof( struct P2PFooter ) );
-+ p += sizeof( struct P2PFooter );
-+
-+ g_snprintf( cmd, sizeof( cmd ), "MSG %d D %d\r\n", ++sb->trId, len );
-+
-+ if( !( msn_sb_write( sb, cmd, strlen( cmd ) ) && msn_sb_write( sb, buffer, len ) ) )
-+ {
-+ do_error_dialog( gc, "Error writing to switchboard in p2p_sendpacket()", "MSN" );
-+ }
-+
-+ g_free( buffer );
-+
-+}
-+
-+
-+/*
-+ * Sends an ACK packet to the sb
-+ */
-+void p2p_sendack( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet )
-+{
-+ if( !packet )
-+ return;
-+
-+ packet->header.id++;
-+ packet->header.offset = 0;
-+ packet->header.total_size = received_packet->header.total_size;
-+ packet->header.length = 0;
-+ packet->header.flags = 0x2;
-+ packet->header.ack_sub_id = received_packet->header.ack_id;
-+ packet->header.ack_id = received_packet->header.id;
-+ packet->header.ack_size = received_packet->header.length;
-+ packet->footer.value = 0;
-+
-+ p2p_sendpacket( sb, packet );
-+}
-+
-+/*
-+ * Sends the base identifier packet to the sb
-+ */
-+void p2p_sendbaseidentifier( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet )
-+{
-+ if( !packet )
-+ return;
-+
-+ packet->header.session_id = 0;
-+ packet->header.offset = 0;
-+ packet->header.total_size = received_packet->header.total_size;
-+ packet->header.flags = 0x2;
-+ packet->header.ack_sub_id = received_packet->header.ack_id;
-+ packet->header.ack_id = received_packet->header.id;
-+ packet->header.id = p2p_randomnr();
-+ packet->header.ack_size = received_packet->header.length;
-+ packet->header.length = 0;
-+
-+ packet->footer.value = 0;
-+
-+ p2p_sendpacket( sb, packet );
-+
-+ packet->header.id -= 4;
-+}
-+
-+/*
-+ * Send's the "200 OK" message to the sb
-+ */
-+void p2p_send200ok( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet )
-+{
-+ struct gaim_connection *gc = sb->gc;
-+ char body[1024];
-+
-+ if( !packet )
-+ return;
-+
-+ packet->header.session_id = 0;
-+ packet->header.id++;
-+ packet->header.offset = 0;
-+
-+ g_snprintf( body, sizeof( body ), "SessionID: %d\r\n\r\n", packet->session_id );
-+
-+ bzero( packet->data, sizeof( packet->data ) );
-+
-+ packet->header.total_size = g_snprintf( packet->data, sizeof( packet->data ),
-+ "MSNSLP/1.0 200 OK\r\n"
-+ "To: <msnmsgr:%s>\r\n"
-+ "From: <msnmsgr:%s>\r\n"
-+ "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n"
-+ "CSeq: %d\r\n"
-+ "Call-ID: {%s}\r\n"
-+ "Max-Forwards: 0\r\n"
-+ "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
-+ "Content-Length: %d\r\n\r\n"
-+ "%s",
-+ packet->destination, gc->username, packet->branch, ++packet->cseq,
-+ packet->call_id, strlen( body )+1 /*adding up the \x00 in the content-length*/ , body );
-+
-+ packet->header.total_size++; /* we need the \x00 at the end */
-+ packet->header.length = packet->header.total_size;
-+ packet->header.flags = 0;
-+ packet->header.ack_id = received_packet->header.id;
-+ packet->header.ack_sub_id = 0;
-+ packet->header.ack_size = 0;
-+
-+ packet->footer.value = 0;
-+
-+ p2p_sendpacket( sb, packet );
-+}
-+
-+/*
-+ * Sends the DATA PREPARATION packet to the sb
-+ */
-+void p2p_senddataprep( struct msn_switchboard *sb, struct P2PPacket *packet )
-+{
-+ if( !packet )
-+ return;
-+
-+ packet->header.session_id = packet->session_id;
-+ packet->header.id++;
-+ packet->header.offset = 0;
-+ packet->header.total_size = 4;
-+ packet->header.length = 4;
-+ packet->header.flags = 0;
-+ packet->header.ack_id = p2p_randomnr();
-+ packet->header.ack_sub_id = 0;
-+ packet->header.ack_size = 0;
-+
-+ bzero( packet->data, sizeof( packet->data ) );
-+
-+ packet->footer.value = 0x01000000;
-+
-+ p2p_sendpacket( sb, packet );
-+}
-+
-+/*
-+ * Sends data( picture data ) to the sb
-+ * splitting it into multiple messages if required
-+ */
-+void p2p_senddata( struct msn_switchboard *sb, struct P2PPacket *packet )
-+{
-+ int fd, bytes;
-+ struct stat fileinfo;
-+
-+ if( !packet )
-+ return;
-+
-+ if( !packet->filename )
-+ return;
-+
-+ if( ( fd=open( packet->filename, O_RDONLY ) ) == -1 )
-+ return;
-+
-+ if( fstat( fd, &fileinfo ) != 0 )
-+ {
-+ close( fd );
-+ return;
-+ }
-+
-+ packet->header.id++;
-+ packet->header.total_size = fileinfo.st_size;
-+ packet->header.flags = 0x20;
-+ packet->header.ack_sub_id = 0;
-+ packet->header.ack_size = 0;
-+ packet->header.offset = 0;
-+
-+ packet->footer.value = 0x01000000;
-+
-+#define MAX_CHUNK_SIZE 1200
-+ while(( bytes = read( fd, packet->data, MAX_CHUNK_SIZE ) ) > 0 ) {
-+ packet->header.ack_id = p2p_randomnr();
-+ packet->header.length = bytes;
-+ p2p_sendpacket( sb, packet );
-+ packet->header.offset += packet->header.length;
-+ }
-+
-+ close( fd );
-+}
-+
-+/*
-+ * sends an INVITE for context to the packet's destination...
-+ */
-+void p2p_sendinvite( struct msn_switchboard *sb, struct P2PPacket *packet, char *context )
-+{
-+ struct gaim_connection *gc = sb->gc;
-+ char body[1024];
-+
-+ packet->session_id = p2p_randomnr();
-+
-+ if( packet->fd == -1 )
-+ {
-+ do_error_dialog( gc, "Couldn't send an INVITE because the current packet hasn't got an open file to write to! WTF?", "MSN" );
-+ return;
-+ }
-+
-+ if( packet->branch )
-+ {
-+ g_free( packet->branch );
-+ }
-+ packet->branch = p2p_rand_guid();
-+
-+ if( packet->call_id )
-+ {
-+ g_free( packet->call_id );
-+ }
-+ packet->call_id = p2p_rand_guid();
-+
-+ packet->header.session_id = 0;
-+ packet->header.id = p2p_randomnr();
-+ packet->header.offset = 0;
-+
-+ g_snprintf( body, sizeof( body ),
-+ "\r\n"
-+ "EUF-GUID: {A4268EEC-FEC5-49E5-95C3-F126696BDBF6}\r\n"
-+ "SessionID: %d\r\n"
-+ "AppID: 1\r\n"
-+ "Context: %s\r\n",
-+ packet->session_id, context );
-+
-+ bzero( packet->data, sizeof( packet->data ) );
-+
-+ packet->header.total_size = g_snprintf( packet->data, sizeof( packet->data ),
-+ "INVITE MSNMSGR:%s MSNSLP/1.0\r\n"
-+ "To: <msnmsgr:%s>\r\n"
-+ "From: <msnmsgr:%s>\r\n"
-+ "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n"
-+ "CSeq: 0\r\n"
-+ "Call-ID: {%s}\r\n"
-+ "Max-Forwards: 0\r\n"
-+ "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
-+ "Content-Length: %d\r\n"
-+ "%s",
-+ packet->destination, packet->destination, gc->username, packet->branch, packet->call_id, strlen( body )+1, body );
-+
-+ packet->header.total_size++;
-+
-+ packet->header.length = packet->header.total_size;
-+ packet->header.flags = 0;
-+ packet->header.ack_id = p2p_randomnr();
-+ packet->header.ack_sub_id = 0;
-+ packet->header.ack_size = 0;
-+
-+ packet->footer.value = 0;
-+
-+ sb->p2p_sessionlist = g_slist_append( sb->p2p_sessionlist, packet );
-+
-+ packet->next_step_on_ack = BASEIDENTIFIER;
-+
-+ p2p_sendpacket( sb, packet );
-+}
-+
-+/*
-+ * request an msnobject from a user, it'll convert the msnobject to a context for p2p_sendinvite()
-+ * makes a fullpath using msn_imagefullpath() and opens that file for writing, add the filedescriptor
-+ * to the packet and then sends the invite...
-+ * if emo_msnobject is NULL we'll request the user's buddy-image, else emo_msnobject
-+ * is requested as an emoticon...
-+ */
-+void p2p_request_msnobject( struct msn_switchboard *sb, char *destination, char *emo_msnobject, char *emoticon_shortcut)
-+{
-+ struct gaim_connection *gc = sb->gc;
-+ struct msn_data *md = gc->proto_data;
-+ char *context = NULL, *msnobject = NULL;
-+ struct P2PPacket *packet;
-+ int type = -1;
-+
-+ if( emo_msnobject == NULL ) /* we need to request the user's msnobject for buddy-image */
-+ {
-+ struct msn_userinfo *userinfo = msn_find_userinfo( md, destination );
-+ if( userinfo )
-+ {
-+ msnobject = userinfo->msnobject;
-+ context = msnobject_to_context( userinfo->msnobject );
-+ type = TYPE_BUDDY_IMAGE;
-+ }
-+ else
-+ {
-+ /* Requesting a buddy-image from a user that doesn't have one ???
-+ * return! we shouldn't be doing anything then!
-+ */
-+ return;
-+ }
-+ }
-+ else /* We'll request an emoticon... */
-+ {
-+ msnobject = emo_msnobject;
-+ context = msnobject_to_context( emo_msnobject );
-+ type = TYPE_EMOTICON_IMAGE;
-+ }
-+
-+ if( context )
-+ {
-+ packet = p2p_packet_new();
-+
-+ if ( packet )
-+ {
-+ char *filename = NULL;
-+ char *emoticon_info_filename = NULL;
-+
-+ packet->destination = g_strdup( destination );
-+ switch( type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ filename = msn_imagefullpath( gc, packet->destination, msnobject, type, emoticon_shortcut, "png" );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ filename = msn_imagefullpath( gc, packet->destination, msnobject, type, emoticon_shortcut, "png" );
-+ if( emoticon_shortcut )
-+ {
-+ emoticon_info_filename = msn_imagefullpath( gc, packet->destination, msnobject, type, emoticon_shortcut, "emo" );
-+ if( emoticon_info_filename )
-+ {
-+ FILE *fp;
-+ fp = fopen( emoticon_info_filename, "w" );
-+ if( fp )
-+ {
-+ fprintf( fp, "SHORTCUT=%s\n", emoticon_shortcut );
-+ fprintf( fp, "PNGFILE=%s\n", filename );
-+ fclose( fp );
-+ }
-+ else
-+ {
-+ do_error_dialog( gc, "Could not open this emoticon's .emo file for writing!!!", "MSN" );
-+ g_free( filename );
-+ filename = NULL;
-+ }
-+ g_free( emoticon_info_filename );
-+ emoticon_info_filename = NULL;
-+ }
-+ else
-+ {
-+ g_free( filename );
-+ filename = NULL;
-+ }
-+ }
-+ else
-+ {
-+ /* This should never be reached! */
-+ do_error_dialog( gc, "Requesting TYPE_EMOTICON_IMAGE without a valid emoticon_shortcut", "MSN" );
-+ }
-+ break;
-+ default:
-+ /* In fact we should never reach this peace of code! */
-+ do_error_dialog( gc, "Requesting an unknown msnobject type? Not even trying that! ...", "MSN" );
-+ break;
-+ }
-+
-+
-+ if( filename )
-+ {
-+ if( emoticon_shortcut )
-+ {
-+ char buffer[1024];
-+ int len = g_snprintf( buffer, sizeof( buffer ),
-+ "<<bitlbee>> %s is an emoticon ( %s )",
-+ emoticon_shortcut, filename );
-+ serv_got_im( gc, destination, buffer, 0, 0, len );
-+ }
-+
-+ if( access( filename, F_OK ) == 0 )
-+ {
-+ switch( type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ serv_got_crap( gc, "Not downloading buddy image from %s because we already have it cached!",
-+ packet->destination );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ serv_got_crap( gc, "Not downloading emoticon image from %s because we already have it cached!",
-+ packet->destination );
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ packet->fd = open( filename, O_WRONLY|O_TRUNC|O_CREAT, 00777 );
-+
-+ if ( packet->fd != -1 )
-+ {
-+ switch( type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ serv_got_crap( gc, "Saving %s's buddy image to: %s",
-+ packet->destination, filename );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ serv_got_crap( gc, "Saving emoticon '%s' from %s to: %s",
-+ emoticon_shortcut, packet->destination, filename );
-+ break;
-+ }
-+
-+ if( packet->filename )
-+ {
-+ g_free( packet->filename );
-+ }
-+ packet->filename = g_strdup( filename );
-+ packet->type = type;
-+
-+ /* p2p_sendinvite will add packet to the md->p2p_sessionlist so it'll
-+ * be g_free()'ed at the right time!
-+ */
-+ p2p_sendinvite( sb, packet, context );
-+ }
-+ else
-+ {
-+ switch( type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ do_error_dialog( gc, "Couldn't write to the buddy images directory. Please check your 'msn_images_path_buddy' setting! Not requesting the msnobject!", "MSN" );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ do_error_dialog( gc, "Couldn't write to the emoticon images directory. Please check your 'msn_images_path_emoticon' setting! Not requesting the msnobject!", "MSN" );
-+ break;
-+ }
-+ }
-+ }
-+
-+ g_free( filename );
-+ }
-+ else
-+ {
-+ switch( type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ do_error_dialog( gc, "Please check your 'msn_images_path_buddy' setting. It doesn't seem to be a valid directory!", "MSN" );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ do_error_dialog( gc, "Please check your 'msn_images_path_emoticon' setting. It doesn't seem to be a valid directory!", "MSN" );
-+ break;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ do_error_dialog( gc, "Could not allocate memory for 'packet' in p2p_request_msnobject()", "MSN" );
-+ }
-+
-+ g_free( context );
-+ }
-+ else
-+ {
-+ do_error_dialog( gc, "Couldn't create context for msnobject in p2p_request_msnobject()", "MSN" );
-+ }
-+
-+}
-+
-+/*
-+ * Send BYE packet to sb
-+ */
-+void p2p_sendbye( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet )
-+{
-+ struct gaim_connection *gc = sb->gc;
-+
-+ if( !packet )
-+ return;
-+
-+ packet->header.session_id = 0;
-+ packet->header.id++;
-+ packet->header.offset = 0;
-+
-+ bzero( packet->data, sizeof( packet->data ) );
-+
-+ packet->header.total_size = g_snprintf( packet->data, sizeof( packet->data ),
-+ "BYE MSNMSGR:%s MSNSLP/1.0\r\n"
-+ "To: <msnmsgr:%s>\r\n"
-+ "From: <msnmsgr:%s>\r\n"
-+ "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n"
-+ "CSeq: 0\r\n"
-+ "Call-ID: {%s}\r\n"
-+ "Max-Forwards: 0\r\n"
-+ "Content-Type: application/x-msnmsgr-sessionclosebody\r\n"
-+ "Content-Length: 3\r\n\r\n",
-+ packet->destination, packet->destination, gc->username, packet->branch, packet->call_id );
-+
-+ packet->header.total_size++; /* we need a \x00 at the end! */
-+ packet->header.length = packet->header.total_size;
-+
-+ packet->header.flags = 0;
-+ packet->header.ack_id = received_packet->header.id;
-+ packet->header.ack_sub_id = 0;
-+ packet->header.ack_size = 0;
-+
-+ packet->footer.value = 0;
-+
-+ p2p_sendpacket( sb, packet );
-+}
-+
-+void log_packet(struct P2PPacket *packet, char *dir)
-+{
-+/*
-+FILE *fp;
-+fp=fopen("/tmp/log.akke","a");
-+fprintf(fp, "\r\n%s START-----------------------------------------------\r\n", dir);
-+fprintf(fp, "header:\n");
-+fprintf(fp, " session_id: %d\n", packet->header.session_id);
-+fprintf(fp, " id: %d\n", packet->header.id);
-+fprintf(fp, " offset: %llu\n", packet->header.offset);
-+fprintf(fp, " len: %llu\n", packet->header.total_size);
-+fprintf(fp, " length: %d\n", packet->header.length);
-+fprintf(fp, " flags: %d\n", packet->header.flags);
-+fprintf(fp, " ack_id: %d\n", packet->header.ack_id);
-+fprintf(fp, " ack_sub_id: %d\n", packet->header.ack_sub_id);
-+fprintf(fp, " ack_size: %llu\n", packet->header.ack_size);
-+if (packet->header.length > 0)
-+{
-+ fprintf(fp, "data:\n");
-+ fprintf(fp, "%s\n", packet->data);
-+}
-+fprintf(fp, "footer:\n");
-+fprintf(fp, " value: %d\n", packet->footer.value);
-+fprintf(fp, "\r\n%s STOP-----------------------------------------------\r\n", dir);
-+fclose(fp);
-+*/
-+}
-+
-+
-+/*
-+ * Main handler. Will parse all P2P/SLP messages and handle it appropriate..
-+ */
-+void p2p_handler( struct msn_switchboard *sb, struct P2PPacket *packet )
-+{
-+ struct gaim_connection *gc = sb->gc;
-+ struct P2PPacket *tmp_packet;
-+
-+ log_packet(packet, "IN");
-+ /* if this is an ACK packet */
-+ if( packet->header.flags == 0x2 )
-+ {
-+ debug( "P2P: ACK received..." );
-+
-+ /* Check if any of our sessions is waiting for an ACK */
-+ tmp_packet = p2p_find_packet( sb, packet->header.ack_id, FIND_BY_ID );
-+ if( tmp_packet )
-+ {
-+ debug( "session found by FIND_BY_ID ..." );
-+ switch( tmp_packet->next_step_on_ack )
-+ {
-+ /* Sending image part */
-+ case DATA_PREP:
-+ debug( "Ok! Now sending data preparation..." );
-+
-+ tmp_packet->next_step_on_ack = SEND_DATA;
-+ p2p_senddataprep( sb, tmp_packet );
-+
-+ break;
-+
-+ case SEND_DATA:
-+ debug( "Ok! Now sending the data...");
-+
-+ tmp_packet->next_step_on_ack = DATA_SENT;
-+ p2p_senddata( sb, tmp_packet );
-+ switch( tmp_packet->type )
-+ {
-+ case TYPE_BUDDY_IMAGE:
-+ serv_got_crap( gc, "%s downloaded my buddy image!",
-+ tmp_packet->destination );
-+ break;
-+ case TYPE_EMOTICON_IMAGE:
-+ serv_got_crap( gc, "%s downloaded my emoticon image %s!",
-+ tmp_packet->destination, tmp_packet->filename );
-+ break;
-+ }
-+
-+ break;
-+
-+ case DATA_SENT:
-+ debug( "Ok! This is the data sent ack. Nothing to be done..." );
-+ tmp_packet->next_step_on_ack = -1;
-+ serv_got_crap( gc, "My buddy image successfully sent to %s",
-+ tmp_packet->destination );
-+ break;
-+
-+ /* Receiving image part */
-+ case BASEIDENTIFIER:
-+ debug( "Ok! This is the base identifier. Nothing to be done..." );
-+ break;
-+
-+ case BYEACK:
-+ debug( "Ok! This is an ACK to my bye msg. Deleting session..." );
-+ p2p_cleanup_packet( tmp_packet );
-+ sb->p2p_sessionlist = g_slist_remove( sb->p2p_sessionlist, tmp_packet );
-+
-+ break;
-+
-+ default:
-+ debug( "huh? I don't expect any ACK!!! ERROR ERROR??" );
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ debug( "hmm, i couldn't find a session for this ack. Ignoring packet...");
-+ return; /* ignore ACK packet */
-+ }
-+ } else
-+
-+ /* Check if this is an INVITE packet */
-+ if( !strncmp( packet->data, "INVITE MSNMSGR", strlen( "INVITE MSNMSGR" ) ) )
-+ {
-+ char *session_id = p2p_findheader( packet, "SessionID:" );
-+ char *dest = p2p_findheader( packet, "From: <msnmsgr:" );
-+ char *branch = p2p_findheader( packet, "branch={" );
-+ char *call_id = p2p_findheader( packet, "Call-ID: {" );
-+ char *cseq = p2p_findheader( packet, "CSeq:" );
-+ char *content_type = p2p_findheader( packet, "Content-Type:" );
-+
-+ if( session_id && dest && branch && call_id && cseq && content_type )
-+ {
-+ dest[strlen( dest )-1]=0;
-+ branch[strlen( branch )-1]=0;
-+ call_id[strlen( call_id )-1]=0;
-+
-+ if( !strncmp( content_type, "application/x-msnmsgr-sessionreqbody", strlen( "application/x-msnmsgr-sessionreqbody" ) ) )
-+ {
-+ char *eufguid = p2p_findheader( packet, "EUF-GUID: {" );
-+ char *appid = p2p_findheader( packet, "AppID:" );
-+ char *context = p2p_findheader( packet, "Context:" );
-+
-+ if( eufguid && appid && context )
-+ {
-+ eufguid[strlen( eufguid )-1]=0;
-+
-+ /* Check eufguid, A4268EEC-FEC5-49E5-95C3-F126696BDBF6 = emoticon or buddy image */
-+ if( !strncmp( eufguid, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6", strlen( "A4268EEC-FEC5-49E5-95C3-F126696BDBF6" ) ) )
-+ {
-+ /* buddy image or emoticon */
-+ packet->destination = g_strdup( dest );
-+ packet->session_id = atoi( session_id );
-+ packet->fd = -1;
-+ packet->next_step_on_ack = -1;
-+
-+ sb->p2p_sessionlist = g_slist_append( sb->p2p_sessionlist, packet );
-+
-+ p2p_sendbaseidentifier( sb, packet, packet );
-+
-+ debug( "Sent base identifier...");
-+ }
-+
-+
-+ if( !strncmp( appid, "1", 1 ) )
-+ {
-+ //todo: check context, if it's a buddy or emoticon and if it's valid..
-+ // then use msn_images_mybuddyimage and probably create a new
-+ // option msn_images_myemoticonimages
-+ // blabla.. you get the point..
-+ char *my_buddy_image = set_getstr( gc->irc, "msn_images_mybuddyimage" );
-+ if( access( my_buddy_image, R_OK ) == 0 )
-+ {
-+ packet->next_step_on_ack = DATA_PREP;
-+ packet->filename = g_strdup( my_buddy_image );
-+ packet->branch = g_strdup( branch );
-+ packet->call_id = g_strdup( call_id );
-+ packet->cseq = atoi( cseq );
-+ packet->type = TYPE_BUDDY_IMAGE; // we don't support sending emoticons so this is ok for now ...
-+ p2p_send200ok( sb, packet, packet );
-+ debug( "Sent 200 OK message" );
-+ }
-+ else
-+ {
-+ debug( "Buddy Image not sent!!" );
-+ do_error_dialog( gc, "Buddy image not sent!", "MSN");
-+ // todo: send an error back instead of leaving the session unterminated!
-+ }
-+ } else
-+
-+ if( !strncmp( appid, "2", 1 ) )
-+ {
-+ // todo: for filetransfers the INVITE message kan have a totalsize != length
-+ // because the preview data is at the context field
-+ // therefor we need to concatenate INVITE messages until offset+length = totalsize
-+ // before parsing the invite message
-+ // YOU NEED TO FIX THAT *BEFORE* starting to implement the filetransfer code
-+ do_error_dialog( gc, "TODO: Complete filetransfer code!", "MSN" );
-+ }
-+ }
-+
-+ if( appid )
-+ g_free( appid );
-+ if( context )
-+ g_free( context );
-+ if( eufguid )
-+ g_free( eufguid );
-+ }
-+ }
-+
-+ if( session_id )
-+ g_free( session_id );
-+ if( dest )
-+ g_free( dest );
-+ if( branch )
-+ g_free( branch );
-+ if( call_id )
-+ g_free( call_id );
-+ if( cseq )
-+ g_free( cseq );
-+ if( content_type )
-+ g_free( content_type );
-+ } else
-+
-+ /* If this is a 200 OK response */
-+ if( !strncmp( packet->data, "MSNSLP/1.0 200 OK", strlen( "MSNSLP/1.0 200 OK" ) ) )
-+ {
-+ char *call_id = p2p_findheader( packet, "Call-ID: {" );
-+ if( call_id )
-+ {
-+ call_id[strlen( call_id )-1]=0;
-+
-+ tmp_packet = p2p_find_packet_by_callid( sb, call_id );
-+ if( tmp_packet )
-+ {
-+ debug( "200 OK message received. Sending an ACK" );
-+ p2p_sendack( sb, tmp_packet, packet );
-+ tmp_packet->header.session_id = tmp_packet->session_id;
-+ }
-+ else
-+ {
-+ debug( "200 OK message received but i don't have a session for it... Ignoring!" );
-+ }
-+
-+ g_free( call_id );
-+ }
-+ } else
-+
-+ /* If this is a BYE response */
-+ if( !strncmp( packet->data, "BYE MSNMSGR:", strlen( "BYE MSNMSGR:" ) ) )
-+ {
-+ debug( "BYE message received." );
-+ char *call_id = p2p_findheader( packet, "Call-ID: {" );
-+ if( call_id )
-+ {
-+ call_id[strlen( call_id )-1]=0;
-+
-+ struct P2PPacket *tmp_packet = p2p_find_packet_by_callid( sb, call_id );
-+ if( tmp_packet )
-+ {
-+ debug( "Sending an ACK + BYE message + deleting the session!" );
-+ tmp_packet->header.session_id = 0;
-+ p2p_sendack( sb, tmp_packet, packet );
-+
-+ p2p_cleanup_packet( tmp_packet );
-+ sb->p2p_sessionlist = g_slist_remove( sb->p2p_sessionlist, tmp_packet );
-+ }
-+ else
-+ {
-+ debug( "I don't expect a BYE message. Ignoring message" );
-+ }
-+
-+ g_free( call_id );
-+ }
-+ } else
-+
-+ /* MSN Messenger 6.2 sends a message back with flag being 0x40
-+ * right after downloading our buddy image. I can't find any
-+ * '3rd-party documentation' about that flag but everything seems
-+ * to be working so i guess it's a normal thing?
-+ * If you know more about that flag: I'm interested to know about it!
-+ * (maybe there's an error in any of my packets and 0x40 means ERROR?)
-+ */
-+ if( packet->header.flags == 0x40 )
-+ {
-+ /* IGNORE */
-+ } else
-+
-+ /* Check for data preparation / data messages packets */
-+ if( packet->header.session_id != 0 )
-+ {
-+ tmp_packet = p2p_find_packet( sb, packet->header.session_id, FIND_BY_SESSION_ID );
-+ if( tmp_packet )
-+ {
-+ if( packet->header.total_size == 4 && packet->header.length == 4 )
-+ {
-+ /* Data preparation received */
-+ if( tmp_packet->filename )
-+ {
-+ debug( "Data perparation received. Sending ACK..." );
-+ p2p_sendack( sb, tmp_packet, packet );
-+ }
-+ else
-+ {
-+ debug( "Got a data preparation message but no filename to write to. THIS SHOULD'NT HAPPEN!" );
-+ }
-+ }
-+ else
-+ {
-+ /* Data message received */
-+ debug( "Data message ... Data is comming!!!" );
-+
-+ if( tmp_packet->fd != -1 )
-+ {
-+ if( write( tmp_packet->fd, packet->data, packet->header.length ) == -1 )
-+ {
-+ debug( "Error writing buddy/emoticon data! This shouldn't hapen :(" );
-+ }
-+ else
-+ {
-+ debug( "buddy/emoticon data written successfully!" );
-+ }
-+ }
-+ else
-+ {
-+ debug( "Got a data packet but i don't have a file to write to. This should not happen!" );
-+ }
-+
-+ if( packet->header.offset + packet->header.length >= packet->header.total_size )
-+ {
-+ /* end of file */
-+ debug( "File receive completed!" );
-+ serv_got_crap( gc, "File %s received successfully!",
-+ tmp_packet->filename );
-+
-+ if( tmp_packet->fd != -1 )
-+ {
-+ close( tmp_packet->fd );
-+ tmp_packet->fd = -1;
-+
-+ }
-+ p2p_sendack( sb, tmp_packet, packet );
-+ tmp_packet->next_step_on_ack = BYEACK;
-+ p2p_sendbye( sb, tmp_packet, packet );
-+ }
-+ }
-+ }
-+ else
-+ {
-+ /* SHOULD NOT HAPPEN */
-+ debug( "Well this shouldn't happen, Reference: 239OJPA2" );
-+ }
-+ } else
-+
-+ /* something else */
-+ {
-+ /* Unsupported? */
-+ debug( "received a p2p packet but don't know how to handle it (yet?)" );
-+ }
-+}
-diff -urN bitlbee-0.92/protocols/msn/msnc1.h bitlbee-0.92.akke/protocols/msn/msnc1.h
---- bitlbee-0.92/protocols/msn/msnc1.h 1970-01-01 01:00:00.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/msnc1.h 2005-05-07 02:41:33.000000000 +0200
-@@ -0,0 +1,82 @@
-+#ifndef MSNC1
-+#define MSNC1
-+
-+#define DWORD unsigned int
-+#define QWORD unsigned long long
-+
-+struct P2PHeader
-+{
-+ DWORD session_id;
-+ DWORD id;
-+ QWORD offset;
-+ QWORD total_size;
-+ DWORD length;
-+ DWORD flags;
-+ DWORD ack_id;
-+ DWORD ack_sub_id;
-+ QWORD ack_size;
-+};
-+
-+struct P2PFooter
-+{
-+ DWORD value;
-+};
-+
-+struct P2PPacket
-+{
-+ /* msn p2p stuff */
-+ struct P2PHeader header;
-+ char data[1352]; /* max. 1202 characters ( or 1352 in case of a Direct Connection ( not even supported by now! ) ) */
-+ struct P2PFooter footer;
-+
-+ /* msn slp stuff */
-+ char *destination, *branch, *call_id, *filename;
-+ int cseq, session_id;
-+ int type, next_step_on_ack;
-+ int fd;
-+};
-+
-+enum {
-+ FIND_BY_SESSION_ID = 1,
-+ FIND_BY_ID,
-+};
-+
-+enum {
-+ IGNORE = 1,
-+ DATA_PREP,
-+ SEND_DATA,
-+ DATA_SENT,
-+ BASEIDENTIFIER,
-+ BYEACK,
-+};
-+
-+void msn_update_mybuddyimage( struct gaim_connection *gc );
-+struct msn_userinfo *msn_find_userinfo( struct msn_data *md, char *who );
-+void msn_cleanup_userinfo( struct msn_userinfo *userinfo );
-+void msn_cleanup_userinfolist( struct msn_data *md );
-+void msn_add_or_update_userinfolist( struct gaim_connection *gc, struct msn_userinfo *new_userinfo );
-+struct msn_userinfo *userinfo_from_params( char *who, char *msnobject );
-+void p2p_init_random();
-+DWORD p2p_randomnr();
-+char *p2p_rand_guid();
-+struct P2PPacket *p2p_packet_new();
-+struct P2PPacket *p2p_packet_from_buffer( char *buffer, int length );
-+struct P2PPacket *p2p_find_packet_by_callid( struct msn_switchboard *sb, char *call_id );
-+struct P2PPacket *p2p_find_packet( struct msn_switchboard *sb, DWORD value, int type );
-+char *p2p_findheader( struct P2PPacket *packet, char *header );
-+void p2p_cleanup_packet( struct P2PPacket *packet );
-+void p2p_cleanup_sb( struct msn_switchboard *sb );
-+char *msn_imagefullpath( struct gaim_connection *gc, char *who, char *msnobject, int type, char *emoticon_shortcut, char *ext );
-+void p2p_sendpacket( struct msn_switchboard *sb, struct P2PPacket *packet );
-+void p2p_sendack( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet );
-+void p2p_sendbaseidentifier( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet );
-+void p2p_send200ok( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet );
-+void p2p_senddataprep( struct msn_switchboard *sb, struct P2PPacket *packet );
-+void p2p_senddata( struct msn_switchboard *sb, struct P2PPacket *packet );
-+void p2p_sendinvite( struct msn_switchboard *sb, struct P2PPacket *packet, char *context );
-+void p2p_request_msnobject( struct msn_switchboard *sb, char *destination, char *msnobject, char *emoticon_shortcut );
-+void p2p_sendbye( struct msn_switchboard *sb, struct P2PPacket *packet, struct P2PPacket *received_packet );
-+void p2p_handler( struct msn_switchboard *sb, struct P2PPacket *packet );
-+
-+#endif
-+
-diff -urN bitlbee-0.92/protocols/msn/msnobject.c bitlbee-0.92.akke/protocols/msn/msnobject.c
---- bitlbee-0.92/protocols/msn/msnobject.c 1970-01-01 01:00:00.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/msnobject.c 2005-05-07 02:30:12.000000000 +0200
-@@ -0,0 +1,156 @@
-+#include "msnobject.h"
-+#include "msn.h"
-+
-+/*
-+ * BASE64 encoding, functions comes from yahoo protocol module
-+ * just some little mods..
-+ */
-+static char msn_base64digits[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-+ "abcdefghijklmnopqrstuvwxyz"
-+ "0123456789+/=";
-+void msn_tobase64( unsigned char *out, const unsigned char *in, int inlen )
-+{
-+ for ( ; inlen >= 3; inlen -= 3 )
-+ {
-+ *out++ = msn_base64digits[in[0] >> 2];
-+ *out++ = msn_base64digits[( ( in[0]<<4 ) & 0x30 ) | ( in[1]>>4 )];
-+ *out++ = msn_base64digits[( ( in[1]<<2 ) & 0x3c ) | ( in[2]>>6 )];
-+ *out++ = msn_base64digits[in[2] & 0x3f];
-+ in += 3;
-+ }
-+ if ( inlen > 0 )
-+ {
-+ unsigned char fragment;
-+
-+ *out++ = msn_base64digits[in[0] >> 2];
-+ fragment = ( in[0] << 4 ) & 0x30;
-+ if ( inlen > 1 )
-+ fragment |= in[1] >> 4;
-+ *out++ = msn_base64digits[fragment];
-+ *out++ = ( inlen < 2 ) ? '='
-+ : msn_base64digits[( in[1] << 2 ) & 0x3c];
-+ *out++ = '=';
-+ }
-+ *out = '\0';
-+}
-+
-+/*
-+ * convert an http-encoded msnobject to an msn context
-+ * ( = base64(<http-decoded msnobject>+<\x00>) )
-+ */
-+char *msnobject_to_context( char *msnobject )
-+{
-+ char *buf1, *buf2;
-+ int length = strlen( msnobject );
-+
-+ buf1 = g_new0( char, length + 2 );
-+ if ( !buf1 )
-+ return NULL;
-+
-+ strncpy( buf1, msnobject, length );
-+ http_decode( buf1 );
-+
-+ length = strlen( buf1 );
-+
-+ buf2 = g_new0( char, length * 3 );
-+
-+ if ( !buf2 )
-+ {
-+ g_free( buf1 );
-+ return NULL;
-+ }
-+
-+ msn_tobase64( buf2, buf1, length + 1 );
-+
-+ g_free( buf1 );
-+
-+ return buf2;
-+}
-+
-+/*
-+ * create a new msnobject from the specified parameters
-+ */
-+char *msnobject_from_params( char *creator, int type, char *filename )
-+{
-+ SHA_CTX SHA_Context;
-+ FILE *fd;
-+ struct stat statinfo;
-+ unsigned char digest[20];
-+
-+ char buffer[1024], sha1d[200], sha1c[200], *tmp, *location;
-+ int len;
-+
-+ if ( !filename )
-+ return NULL;
-+
-+ if ( ( stat( filename, &statinfo ) ) != 0 )
-+ return NULL;
-+
-+ if ( !( fd=fopen( filename, "r" ) ) )
-+ return NULL;
-+
-+ tmp = g_strdup( filename );
-+ if ( !tmp )
-+ return NULL;
-+ location = basename( tmp );
-+ g_free( tmp );
-+
-+ /* calculate SHA1D */
-+ shaInit( &SHA_Context );
-+ while ( ( len = fread( buffer, 1, sizeof( buffer ), fd ) ) > 0 )
-+ {
-+ shaUpdate( &SHA_Context, buffer, len );
-+ }
-+ shaFinal( &SHA_Context, digest );
-+ msn_tobase64( sha1d, digest, 20 );
-+ fclose( fd );
-+ http_encode( sha1d );
-+
-+ /* calculate SHA1C */
-+ shaInit( &SHA_Context );
-+ len = g_snprintf( buffer, sizeof( buffer ),
-+ "Creator%sSize%dType%dLocation%sFriendlyAAA=SHA1D%s",
-+ creator, ( int )statinfo.st_size, type, location, sha1d );
-+ shaUpdate( &SHA_Context, buffer, len );
-+ shaFinal( &SHA_Context, digest );
-+ msn_tobase64( sha1c, digest, 20 );
-+ http_encode( sha1c );
-+
-+ /* create msnobject */
-+ g_snprintf( buffer, sizeof( buffer ),
-+ "%%3Cmsnobj%%20Creator%%3D%%22%s%%22%%20Size%%3D%%22%d%%22%%20Type%%3D%%22%d%%22%%20Location%%3D%%22%s%%22%%20Friendly%%3D%%22AAA%%3D%%22%%20SHA1D%%3D%%22%s%%22%%20SHA1C%%3D%%22%s%%22/%%3E",
-+ creator, ( int )statinfo.st_size, type, location, sha1d, sha1c );
-+
-+ return g_strdup( buffer );
-+}
-+
-+/*
-+ * returns a field from an msnobject..
-+ */
-+char *msnobject_get_field( char *field, char *msnobject )
-+{
-+ char *tag = NULL, *start = NULL, *end = NULL, tmp[200];
-+
-+ char *decoded_msnobject = g_new0( char, strlen( msnobject ) * 3 );
-+
-+ if ( !decoded_msnobject )
-+ return NULL;
-+
-+ strcpy( decoded_msnobject, msnobject );
-+ http_decode( decoded_msnobject );
-+
-+ g_snprintf( tmp, sizeof( tmp ), "%s=\"", field );
-+
-+ if ( ( start = strstr( decoded_msnobject, tmp ) ) != NULL )
-+ {
-+ start += strlen( tmp );
-+ end = strchr( start, '"' );
-+ if ( end )
-+ tag = g_strndup( start, end-start );
-+ }
-+
-+ g_free( decoded_msnobject );
-+
-+ return tag;
-+}
-+
-diff -urN bitlbee-0.92/protocols/msn/msnobject.h bitlbee-0.92.akke/protocols/msn/msnobject.h
---- bitlbee-0.92/protocols/msn/msnobject.h 1970-01-01 01:00:00.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/msnobject.h 2005-05-07 02:41:29.000000000 +0200
-@@ -0,0 +1,14 @@
-+#ifndef MSN_OBJECT
-+#define MSN_OBJECT
-+
-+#include "nogaim.h"
-+
-+#define TYPE_EMOTICON_IMAGE 2
-+#define TYPE_BUDDY_IMAGE 3
-+
-+void msn_tobase64( unsigned char *out, const unsigned char *in, int inlen );
-+char *msnobject_to_context( char *msnobject );
-+char *msnobject_from_params( char *creator, int type, char *filename );
-+char *msnobject_get_field(char *field, char *msnobject );
-+
-+#endif
-diff -urN bitlbee-0.92/protocols/msn/ns.c bitlbee-0.92.akke/protocols/msn/ns.c
---- bitlbee-0.92/protocols/msn/ns.c 2005-02-23 18:28:41.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/ns.c 2005-05-07 02:52:38.000000000 +0200
-@@ -26,6 +26,7 @@
- #include <ctype.h>
- #include "nogaim.h"
- #include "msn.h"
-+#include "msnc1.h"
- #include "passport.h"
- #include "md5.h"
-
-@@ -71,7 +72,7 @@
- md->handler->fd = md->fd;
- md->handler->rxq = g_new0( char, 1 );
-
-- g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId );
-+ g_snprintf( s, sizeof( s ), "VER %d MSNP9 CVR0\r\n", ++md->trId );
- if( msn_write( gc, s, strlen( s ) ) )
- {
- gc->inpa = gaim_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, gc );
-@@ -105,7 +106,7 @@
-
- if( strcmp( cmd[0], "VER" ) == 0 )
- {
-- if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 )
-+ if( cmd[2] && strncmp( cmd[2], "MSNP9", 5 ) != 0 )
- {
- hide_login_progress( gc, "Unsupported protocol" );
- signoff( gc );
-@@ -297,6 +298,9 @@
-
- if( list & 1 ) /* FL */
- {
-+ if( set_getint( gc->irc, "msn_buddylist_checks" ) == 1 && ( list & 8 ) == 0 )
-+ serv_got_crap( gc, "\0034Contact %s is in your buddy list but you don't appear in his/her one (yet?)!", cmd[1] );
-+
- add_buddy( gc, NULL, cmd[1], cmd[2] );
- }
- if( list & 2 ) /* AL */
-@@ -309,6 +313,9 @@
- }
- if( list & 8 ) /* RL */
- {
-+ if( set_getint( gc->irc, "msn_buddylist_checks" ) == 1 && ( list & 1 ) == 0 )
-+ serv_got_crap( gc, "\0034Contact %s has got you in his/her buddy list but you don't have him/her in yours!", cmd[1] );
-+
- if( ( list & 6 ) == 0 )
- msn_buddy_ask( gc, cmd[1], cmd[2] );
- }
-@@ -367,7 +374,7 @@
- {
- struct msn_away_state *st;
-
-- if( num_parts != 6 )
-+ if( num_parts != 6 && num_parts != 7 )
- {
- hide_login_progress_error( gc, "Syntax error" );
- signoff( gc );
-@@ -376,6 +383,15 @@
-
- http_decode( cmd[4] );
- serv_buddy_rename( gc, cmd[3], cmd[4] );
-+
-+ if( num_parts == 7 ) /* there's an msnobject at the end! */
-+ {
-+ struct msn_userinfo *userinfo = userinfo_from_params(cmd[3], cmd[6]);
-+ if (userinfo)
-+ {
-+ msn_add_or_update_userinfolist( gc, userinfo );
-+ }
-+ }
-
- st = msn_away_state_by_code( cmd[2] );
- if( !st )
-@@ -395,7 +411,7 @@
- {
- struct msn_away_state *st;
-
-- if( num_parts != 5 )
-+ if( num_parts != 5 && num_parts != 6 )
- {
- hide_login_progress_error( gc, "Syntax error" );
- signoff( gc );
-@@ -404,7 +420,16 @@
-
- http_decode( cmd[3] );
- serv_buddy_rename( gc, cmd[2], cmd[3] );
--
-+
-+ if( num_parts == 6 ) /* there's an msnobject at the end! */
-+ {
-+ struct msn_userinfo *userinfo = userinfo_from_params(cmd[2], cmd[5]);
-+ if (userinfo)
-+ {
-+ msn_add_or_update_userinfolist( gc, userinfo );
-+ }
-+ }
-+
- st = msn_away_state_by_code( cmd[1] );
- if( !st )
- {
-@@ -451,6 +476,29 @@
-
- sb = msn_sb_create( gc, server, port, cmd[4], session );
- sb->who = g_strdup( cmd[5] );
-+
-+ if( set_getint( gc->irc, "msn_notify_openwindow" ) == 1 )
-+ {
-+ char buffer[1024];
-+ int len;
-+ user_t *u;
-+ u = user_findhandle( gc, sb->who );
-+ if( u )
-+ {
-+ len = g_snprintf( buffer, sizeof( buffer ),
-+ "<<bitlbee>> *** %s has opened a conversation window. ***",
-+ u->nick);
-+ }
-+ else
-+ {
-+ len = g_snprintf( buffer, sizeof( buffer ),
-+ "<<bitlbee>> *** %s has opened a conversation window. ***",
-+ sb->who);
-+ }
-+
-+ serv_got_im( gc, sb->who, buffer, 0, 0, len );
-+ }
-+
- }
- else if( strcmp( cmd[0], "ADD" ) == 0 )
- {
-@@ -470,17 +518,32 @@
- /* We got added by someone. If we don't have this person in permit/deny yet, inform the user. */
- for( l = gc->permit; l; l = l->next )
- if( g_strcasecmp( l->data, cmd[4] ) == 0 )
-+ {
-+ if( set_getint( gc->irc, "msn_buddylist_checks" ) == 1 )
-+ serv_got_crap( gc, "\0034Contact %s (which is in your allow-list) has just RE-added/allowed you to his/her buddy list!",
-+ cmd[4] );
- return( 1 );
--
-+ }
- for( l = gc->deny; l; l = l->next )
- if( g_strcasecmp( l->data, cmd[4] ) == 0 )
-+ {
-+ if( set_getint( gc->irc, "msn_buddylist_checks" ) == 1 )
-+ serv_got_crap( gc, "\0034Contact %s (which is in your block-list) has just RE-added you to his/her buddy list!",
-+ cmd[4] );
- return( 1 );
-+ }
-
- msn_buddy_ask( gc, cmd[4], cmd[5] );
- }
- }
- else if( strcmp( cmd[0], "REM" ) == 0 )
- {
-+ if( num_parts == 5 && strcmp( cmd[2], "RL" ) == 0 )
-+ {
-+ if( set_getint( gc->irc, "msn_buddylist_checks" ) == 1 )
-+ serv_got_crap( gc, "\0034Contact %s has just removed you from his/her buddy list!",
-+ cmd[4] );
-+ }
- }
- else if( strcmp( cmd[0], "OUT" ) == 0 )
- {
-diff -urN bitlbee-0.92/protocols/msn/sb.c bitlbee-0.92.akke/protocols/msn/sb.c
---- bitlbee-0.92/protocols/msn/sb.c 2005-02-23 16:50:24.000000000 +0100
-+++ bitlbee-0.92.akke/protocols/msn/sb.c 2005-05-07 03:15:57.000000000 +0200
-@@ -28,6 +28,7 @@
- #include "msn.h"
- #include "passport.h"
- #include "md5.h"
-+#include "msnc1.h"
-
- static void msn_sb_callback( gpointer data, gint source, GaimInputCondition cond );
- static int msn_sb_command( gpointer data, char **cmd, int num_parts );
-@@ -55,6 +56,7 @@
- sb->fd = proxy_connect( host, port, msn_sb_connected, sb );
- if( sb->fd < 0 )
- {
-+ p2p_cleanup_sb ( sb );
- g_free( sb );
- return( NULL );
- }
-@@ -126,10 +128,61 @@
-
- if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 )
- {
-- buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 );
-- i = strlen( MSN_MESSAGE_HEADERS );
-+ char *tmp, *font_face, *font_color, font_colorbuffer[5], font_style[10];
-+ int font_charset, font_pitchandfamily, buffer_size;
-+
-+ /* Font face stuff */
-+ tmp = set_getstr( sb->gc->irc, "msn_font_face" );
-+ if( !tmp )
-+ tmp = "MS Shell Dlg"; /* Default font face */
-+
-+ font_face = g_new0( char, strlen(tmp) * 3 ); /* We don't use g_strdup() because we need *
-+ * a buffer 3 times as big because of http_encode() */
-+ strcpy( font_face, tmp );
-+ http_encode( font_face );
-+
-+ /* Font color stuff */
-+ tmp = set_getstr( sb->gc->irc, "msn_font_color" );
-+ if( !tmp )
-+ tmp = "000000"; /* Default font color (=black) */
-+ font_color = g_strdup( tmp );
-+ if( !font_color || strlen( font_color ) != 6 )
-+ {
-+ do_error_dialog( sb->gc, "Please check your 'msn_font_color' setting. Message not sent!!!", "MSN" );
-+ g_free( font_face );
-+ return( 0 );
-+ }
-+ /* font color fixup: msn server wants BGR instead of RGB style..*/
-+ strncpy( font_colorbuffer, font_color, 2 );
-+ font_color[0] = font_color[4];
-+ font_color[1] = font_color[5];
-+ font_color[4] = font_colorbuffer[0];
-+ font_color[5] = font_colorbuffer[1];
-+
-+ /* Font style styff */
-+ strcpy( font_style, "" );
-+ if( set_getint( sb->gc->irc, "msn_font_bold" ) == 1 )
-+ strcat( font_style, "B");
-+ if( set_getint( sb->gc->irc, "msn_font_italic" ) == 1 )
-+ strcat( font_style, "I");
-+ if( set_getint( sb->gc->irc, "msn_font_overstrike" ) == 1 )
-+ strcat( font_style, "S");
-+ if( set_getint( sb->gc->irc, "msn_font_underline" ) == 1 )
-+ strcat( font_style, "U");
-+
-+ /* Font charset */
-+ font_charset = set_getint( sb->gc->irc, "msn_font_CS" );
-+
-+ /* Font Pitch & Family */
-+ font_pitchandfamily = set_getint( sb->gc->irc, "msn_font_PF" );
-+
-+ buffer_size = strlen( MSN_MESSAGE_HEADERS ) + strlen( font_face ) + strlen( font_style ) + strlen( font_color ) + strlen( text ) * 2;
-+ buf = g_new0( char, buffer_size + 1 );
-+ i = g_snprintf( buf, buffer_size, MSN_MESSAGE_HEADERS, font_face, font_style, font_color, font_charset, font_pitchandfamily );
-+
-+ g_free( font_color );
-+ g_free( font_face );
-
-- strcpy( buf, MSN_MESSAGE_HEADERS );
- for( j = 0; text[j]; j ++ )
- {
- if( text[j] == '\n' )
-@@ -137,6 +190,10 @@
-
- buf[i++] = text[j];
- }
-+FILE *fp;
-+fp = fopen("/tmp/tmp.log","a");
-+fprintf(fp, "%s",buf);
-+fclose(fp);
- }
- else
- {
-@@ -238,6 +295,7 @@
-
- msn_switchboards = g_slist_remove( msn_switchboards, sb );
- md->switchboards = g_slist_remove( md->switchboards, sb );
-+ p2p_cleanup_sb ( sb );
- g_free( sb );
- }
-
-@@ -389,6 +447,11 @@
- }
-
- sb->ready = 1;
-+
-+ if( sb->who )
-+ {
-+ p2p_request_msnobject(sb, sb->who, NULL, NULL );
-+ }
- }
- else if( strcmp( cmd[0], "CAL" ) == 0 )
- {
-@@ -437,7 +500,10 @@
-
- sb->msgq = g_slist_remove( sb->msgq, m );
- }
--
-+
-+ if( sb->who )
-+ p2p_request_msnobject(sb, sb->who, NULL, NULL );
-+
- return( st );
- }
- else if( sb->who )
-@@ -489,6 +555,34 @@
- if( sb->who )
- {
- /* This is a single-person chat, and the other person is leaving. */
-+ char buffer[1024];
-+ int len;
-+
-+ if( cmd[2] && *cmd[2] && set_getint( gc->irc, "msn_notify_timeout" ) == 1 )
-+ {
-+ len = g_snprintf( buffer, sizeof( buffer ),
-+ "<<bitlbee>> *** This conversation has timed out. ***" );
-+ serv_got_im( gc, sb->who, buffer, 0, 0, len );
-+ }
-+ else if( !cmd[2] && set_getint( gc->irc, "msn_notify_closewindow" ) == 1 )
-+ {
-+ user_t *u;
-+ u = user_findhandle( gc, sb->who );
-+ if( u )
-+ {
-+ len = g_snprintf( buffer, sizeof( buffer ),
-+ "<<bitlbee>> *** %s has closed the conversation window. ***",
-+ u->nick);
-+ }
-+ else
-+ {
-+ len = g_snprintf( buffer, sizeof( buffer ),
-+ "<<bitlbee>> *** %s has closed the conversation window. ***",
-+ sb->who);
-+ }
-+ serv_got_im( gc, sb->who, buffer, 0, 0, len );
-+ }
-+
- g_free( sb->who );
- sb->who = NULL;
- sb->ready = 0;
-@@ -544,7 +638,7 @@
-
- if( !num_parts )
- return( 1 );
--
-+
- if( ( body = strstr( msg, "\r\n\r\n" ) ) )
- {
- body += 4;
-@@ -649,6 +743,78 @@
-
- g_free( ct );
- }
-+
-+ else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0)
-+ {
-+ char *p2p = msn_findheader( msg, "P2P-Dest:", msglen );
-+
-+ if ( p2p )
-+ {
-+ struct P2PPacket *packet;
-+ packet = p2p_packet_from_buffer( body, blen );
-+ if ( packet )
-+ {
-+ p2p_handler( sb, packet );
-+ if( g_slist_find( sb->p2p_sessionlist, packet ) == NULL )
-+ {
-+ /* The packet isn't used as a session specifier
-+ * so we should g_free() it here as we don't need it
-+ * anymore now...
-+ * If it's the session sepcifier it'll be g_free()'d
-+ * at the right time (when it's sb is cleaned up)!
-+ */
-+ p2p_cleanup_packet( packet );
-+ g_free( packet );
-+ }
-+ }
-+ else
-+ {
-+ do_error_dialog( gc, "Corrupted application/x-msnmsgrp2p message received", "MSN" );
-+ }
-+ g_free( p2p );
-+ }
-+
-+ g_free( ct );
-+ }
-+ else if( g_strncasecmp( ct, "text/x-mms-emoticon", 19 ) == 0)
-+ {
-+ char *p = strchr( body, '\t' );
-+ if ( p )
-+ {
-+ char *shortcut, *msnobject;
-+
-+ shortcut = g_new0( char, ( ( p-body ) + 1 ) );
-+ if ( !shortcut )
-+ {
-+ do_error_dialog( gc, "Could not allocate memory for 'shortcut' in msn_sb_msg()", "MSN" );
-+ g_free( ct );
-+ return( 1 );
-+ }
-+ strncpy( shortcut, body, ( p-body ) );
-+
-+ p++;
-+
-+ msnobject = g_new0( char, strlen( p ) );
-+ if ( !msnobject )
-+ {
-+ do_error_dialog( gc, "Could not allocate memory for 'msnobject' in msn_sb_msg()", "MSN" );
-+ g_free( shortcut );
-+ g_free( ct );
-+ return( 1 );
-+ }
-+ strncpy( msnobject, p, ( strlen( p ) - 1 ) );
-+
-+ p2p_request_msnobject( sb, sb->who, msnobject, shortcut );
-+
-+ g_free( shortcut );
-+ g_free( msnobject );
-+ }
-+ else
-+ {
-+ do_error_dialog( gc, "Corrupted text/x-mms-emoticon message received", "MSN" );
-+ }
-+ g_free( ct );
-+ }
- else
- {
- g_free( ct );