diff options
author | root | 2006-06-16 01:03:02 -0500 |
---|---|---|
committer | root | 2006-06-16 01:03:02 -0500 |
commit | 9a45660a93d38dfb4f151ac9c26d225c47d51e84 (patch) | |
tree | 099d0ad069e9445e673747c40ed9844111b856d2 | |
parent | 3a476e122f9a90a9b14e2d70d3633cd7f37165a0 (diff) |
./chat-irc/bitlbee/msn.patch: 2006/06/15 sync stable from p4
-rw-r--r-- | chat-irc/bitlbee/msn.patch | 2408 |
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 ); |