From 21029d0fe2b7b11512d2cc67495d590e9df53f85 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 20 Mar 2010 13:56:27 +0000 Subject: Add MSNP11 challenge code which I'll need for doing this SOAP stuff. --- protocols/msn/msn.h | 7 +++- protocols/msn/msn_util.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 84914bc3..4799e226 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module */ @@ -40,6 +40,10 @@ #define QRY_NAME "msmsgs@msnmsgr.com" #define QRY_CODE "Q1P7W2E4J9R8U3S5" +/* This should be MSN Messenger 7.0.0813 */ +#define MSNP11_PROD_KEY "CFHUR$52U_{VIX5T" +#define MSNP11_PROD_ID "PROD0101{0RM?UBW" + #define MSN_SB_NEW -24062002 #define MSN_MESSAGE_HEADERS "MIME-Version: 1.0\r\n" \ @@ -160,6 +164,7 @@ char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); char *msn_http_encode( const char *input ); void msn_msgq_purge( struct im_connection *ic, GSList **list ); +char *msn_p11_challenge( char *challenge ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 668a8b8a..59363439 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Miscellaneous utilities */ @@ -25,6 +25,7 @@ #include "nogaim.h" #include "msn.h" +#include "md5.h" #include int msn_write( struct im_connection *ic, char *s, int len ) @@ -376,3 +377,96 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ) imcb_log( ic, "%s", ret->str ); g_string_free( ret, TRUE ); } + +unsigned int little_endian( unsigned int dw ) +{ +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN + return dw; +#else + /* We're still not sure if this machine is big endian since the + constants above are not that portable. Don't swap bytes, just + force-compose a 32-bit little endian integer. */ + unsigned int ret = 0, i; + char *dst = (char*) (&ret + 1); + + for (i = 0; i < 4; i ++) + { + *(--dst) = dw >> 24; + dw <<= 8; + } + + return ret; +#endif +} + +/* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ + +char *msn_p11_challenge( char *challenge ) +{ + char *output, buf[256]; + md5_state_t md5c; + unsigned char md5Hash[16], *newHash; + unsigned int *md5Parts, *chlStringParts, newHashParts[5]; + long long nHigh = 0, nLow = 0; + int i, n; + + /* Create the MD5 hash */ + md5_init(&md5c); + md5_append(&md5c, (unsigned char*) challenge, strlen(challenge)); + md5_append(&md5c, (unsigned char*) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY)); + md5_finish(&md5c, md5Hash); + + /* Split it into four integers */ + md5Parts = (unsigned int *)md5Hash; + for (i = 0; i < 4; i ++) + { + md5Parts[i] = little_endian(md5Parts[i]); + + /* & each integer with 0x7FFFFFFF */ + /* and save one unmodified array for later */ + newHashParts[i] = md5Parts[i]; + md5Parts[i] &= 0x7FFFFFFF; + } + + /* make a new string and pad with '0' */ + n = g_snprintf(buf, sizeof(buf)-5, "%s%s00000000", challenge, MSNP11_PROD_ID); + /* truncate at an 8-byte boundary */ + buf[n&=~7] = '\0'; + + /* split into integers */ + chlStringParts = (unsigned int *)buf; + + /* this is magic */ + for (i = 0; i < (n / 4) - 1; i += 2) + { + long long temp; + + chlStringParts[i] = little_endian(chlStringParts[i]); + chlStringParts[i+1] = little_endian(chlStringParts[i+1]); + + temp = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF; + nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF; + nLow = nLow + nHigh + temp; + } + nHigh = (nHigh+md5Parts[1]) % 0x7FFFFFFF; + nLow = (nLow+md5Parts[3]) % 0x7FFFFFFF; + + newHashParts[0] ^= nHigh; + newHashParts[1] ^= nLow; + newHashParts[2] ^= nHigh; + newHashParts[3] ^= nLow; + + /* swap more bytes if big endian */ + for (i = 0; i < 4; i ++) + newHashParts[i] = little_endian(newHashParts[i]); + + /* make a string of the parts */ + newHash = (unsigned char *)newHashParts; + + /* convert to hexadecimal */ + output = g_new(char, 33); + for (i = 0; i < 16; i ++) + sprintf(output + i * 2, "%02x", newHash[i]); + + return output; +} -- cgit v1.2.3 From e5a8118236442d51eb202a8bdebe5866449554e4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 20 Mar 2010 17:27:23 +0000 Subject: Added soap.c with a fairly reusable SOAP framework and simple code for sending offline messages. It works somewhat, just that Pidgin shows the messages as empty. :-( --- protocols/msn/Makefile | 2 +- protocols/msn/msn.c | 2 + protocols/msn/msn.h | 9 ++- protocols/msn/ns.c | 2 + protocols/msn/sb.c | 12 +++ protocols/msn/soap.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++ protocols/msn/soap.h | 85 +++++++++++++++++++ 7 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 protocols/msn/soap.c create mode 100644 protocols/msn/soap.h (limited to 'protocols') diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index 6a588613..911f47bd 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -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 soap.o tables.o CFLAGS += -Wall LFLAGS += -r diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 8930847d..49ce9298 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -99,6 +99,8 @@ static void msn_logout( struct im_connection *ic ) g_free( md->grouplist[--md->groupcount] ); g_free( md->grouplist ); + g_free( md->passport_token ); + g_free( md ); } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 4799e226..d57ff796 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -41,8 +41,11 @@ #define QRY_CODE "Q1P7W2E4J9R8U3S5" /* This should be MSN Messenger 7.0.0813 */ -#define MSNP11_PROD_KEY "CFHUR$52U_{VIX5T" -#define MSNP11_PROD_ID "PROD0101{0RM?UBW" +//#define MSNP11_PROD_KEY "CFHUR$52U_{VIX5T" +//#define MSNP11_PROD_ID "PROD0101{0RM?UBW" + +#define MSNP11_PROD_KEY "O4BG@C7BWLYQX?5G" +#define MSNP11_PROD_ID "PROD01065C%ZFN6F" #define MSN_SB_NEW -24062002 @@ -67,6 +70,8 @@ struct msn_data struct msn_handler_data *handler; int trId; + char *passport_token; + char *lock_key; GSList *msgq; GSList *switchboards; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index d78d753a..f9c8ab29 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -736,6 +736,8 @@ static void msn_auth_got_passport_token( struct msn_auth_data *mad ) { char buf[1024]; + md->passport_token = g_strdup( mad->token ); + g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token ); msn_write( ic, buf, strlen( buf ) ); } diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index e9526234..920e7f61 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -28,6 +28,7 @@ #include "msn.h" #include "passport.h" #include "md5.h" +#include "soap.h" static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ); static int msn_sb_command( gpointer data, char **cmd, int num_parts ); @@ -605,6 +606,17 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) int num = atoi( cmd[0] ); const struct msn_status_code *err = msn_status_by_number( num ); + if( num == 217 ) + { + GSList *l; + + for( l = sb->msgq; l; l = l->next ) + { + struct msn_message *m = l->data; + msn_soap_oim_send( ic, m->who, m->text ); + } + } + imcb_error( ic, "Error reported by switchboard server: %s", err->text ); if( err->flags & STATUS_SB_FATAL ) diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c new file mode 100644 index 00000000..d3a022ec --- /dev/null +++ b/protocols/msn/soap.c @@ -0,0 +1,216 @@ +/** soap.c + * + * SOAP-related functions. Some manager at Microsoft apparently thought + * MSNP wasn't XMLy enough so someone stepped up and changed that. This + * is the result. + * + * Copyright (C) 2010 Wilmer van der Gaast + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that is will be useful, + * bit WITHOU ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "http_client.h" +#include "soap.h" +#include "msn.h" +#include "bitlbee.h" +#include "url.h" +#include "misc.h" +#include "base64.h" +#include "xmltree.h" +#include +#include + +typedef enum +{ + MSN_SOAP_OK, + MSN_SOAP_RETRY, + MSN_SOAP_ABORT, +} msn_soap_result_t; + +struct msn_soap_req_data; + +typedef int (*msn_soap_func) ( struct msn_soap_req_data * ); + +struct msn_soap_req_data +{ + void *data; + struct im_connection *ic; + int ttl; + + char *url, *action, *payload; + struct http_request *http_req; + + const struct xt_handler_entry *xml_parser; + msn_soap_func build_request, handle_response, free_data; +}; + +struct msn_soap_oim_send_data +{ + char *to; + char *msg; + int number; + int need_retry; +}; + +static int msn_soap_send_request( struct msn_soap_req_data *req ); + +static int msn_soap_start( struct im_connection *ic, + void *data, + msn_soap_func build_request, + const struct xt_handler_entry *xml_parser, + msn_soap_func handle_response, + msn_soap_func free_data ) +{ + struct msn_soap_req_data *req = g_new0( struct msn_soap_req_data, 1 ); + + req->ic = ic; + req->data = data; + req->xml_parser = xml_parser; + req->build_request = build_request; + req->handle_response = handle_response; + req->free_data = free_data; + req->ttl = 3; + + return msn_soap_send_request( req ); +} + +static void msn_soap_handle_response( struct http_request *http_req ); + +static int msn_soap_send_request( struct msn_soap_req_data *soap_req ) +{ + char *http_req; + url_t url; + + soap_req->build_request( soap_req ); + + url_set( &url, soap_req->url ); + http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host, + soap_req->action, strlen( soap_req->payload ), soap_req->payload ); + + soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS, + http_req, msn_soap_handle_response, soap_req ); + + return soap_req->http_req != NULL; +} + +static void msn_soap_handle_response( struct http_request *http_req ) +{ + struct msn_soap_req_data *soap_req = http_req->data; + int st; + + if( http_req->body_size > 0 ) + { + struct xt_parser *parser; + + parser = xt_new( soap_req->xml_parser, soap_req ); + xt_feed( parser, http_req->reply_body, http_req->body_size ); + xt_handle( parser, NULL, -1 ); + xt_free( parser ); + } + + st = soap_req->handle_response( soap_req ); + + if( st == MSN_SOAP_RETRY && --soap_req->ttl ) + msn_soap_send_request( soap_req ); + else + { + soap_req->free_data( soap_req ); + g_free( soap_req->url ); + g_free( soap_req->action ); + g_free( soap_req->payload ); + g_free( soap_req ); + } +} + +static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_soap_oim_send_data *oim = soap_req->data; + struct im_connection *ic = soap_req->ic; + struct msn_data *md = ic->proto_data; + char *display_name_b64; + + display_name_b64 = tobase64( ic->displayname ); + + soap_req->url = g_strdup( SOAP_OIM_SEND_URL ); + soap_req->action = g_strdup( SOAP_OIM_ACTION_URL ); + soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD, + ic->acc->user, display_name_b64, oim->to, md->passport_token, + MSNP11_PROD_ID, md->lock_key ? : "", oim->number, oim->number, oim->msg ); + + g_free( display_name_b64 ); + + return 1; +} + +static xt_status msn_soap_oim_send_challenge( struct xt_node *node, gpointer data ) +{ + struct msn_soap_req_data *soap_req = data; + struct msn_soap_oim_send_data *oim = soap_req->data; + struct im_connection *ic = soap_req->ic; + struct msn_data *md = ic->proto_data; + + g_free( md->lock_key ); + md->lock_key = msn_p11_challenge( node->text ); + + oim->need_retry = 1; + + return XT_HANDLED; +} + +static const struct xt_handler_entry msn_soap_oim_send_parser[] = { + { "LockKeyChallenge", "detail", msn_soap_oim_send_challenge }, + { NULL, NULL, NULL } +}; + +static int msn_soap_oim_handle_response( struct msn_soap_req_data *soap_req ) +{ + struct msn_soap_oim_send_data *oim = soap_req->data; + + if( soap_req->http_req->status_code == 500 && oim->need_retry ) + { + oim->need_retry = 0; + return MSN_SOAP_RETRY; + } + else if( soap_req->http_req->status_code == 200 ) + return MSN_SOAP_OK; + else + return MSN_SOAP_ABORT; +} + +static int msn_soap_oim_free_data( struct msn_soap_req_data *soap_req ) +{ + struct msn_soap_oim_send_data *oim = soap_req->data; + + g_free( oim->to ); + g_free( oim->msg ); + g_free( oim ); + + return 0; +} + +int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg ) +{ + struct msn_soap_oim_send_data *data; + + data = g_new0( struct msn_soap_oim_send_data, 1 ); + data->to = g_strdup( to ); + data->msg = tobase64( msg ); + data->number = 1; + + return msn_soap_start( ic, data, msn_soap_oim_build_request, + msn_soap_oim_send_parser, + msn_soap_oim_handle_response, + msn_soap_oim_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h new file mode 100644 index 00000000..4e7d6627 --- /dev/null +++ b/protocols/msn/soap.h @@ -0,0 +1,85 @@ +/* soap.h + * + * SOAP-related functions. Some manager at Microsoft apparently thought + * MSNP wasn't XMLy enough so someone stepped up and changed that. This + * is the result. + * + * Copyright (C) 2010 Wilmer van der Gaast + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that is will be useful, + * bit WITHOU ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Thanks to http://msnpiki.msnfanatic.com/ for lots of info on this! */ + +#ifndef __SOAP_H__ +#define __SOAP_H__ + +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#endif +#include "nogaim.h" + + +#define SOAP_HTTP_REQUEST \ +"POST %s HTTP/1.0\r\n" \ +"Host: %s\r\n" \ +"Accept: */*\r\n" \ +"SOAPAction: \"%s\"\r\n" \ +"User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ +"Content-Type: text/xml; charset=utf-8\r\n" \ +"Content-Length: %d\r\n" \ +"Cache-Control: no-cache\r\n" \ +"\r\n" \ +"%s" + + +#define SOAP_OIM_SEND_URL "https://ows.messenger.msn.com/OimWS/oim.asmx" +#define SOAP_OIM_ACTION_URL "http://messenger.msn.com/ws/2004/09/oim/Store" + +#define SOAP_OIM_SEND_PAYLOAD \ +"" \ +"" \ +"" \ + "" \ + "" \ + "" \ + "" \ + "http://messenger.msn.com" \ + "%d" \ + "" \ +"" \ +"" \ + "text" \ + "MIME-Version: 1.0\r\n" \ + "Content-Type: text/plain; charset=UTF-8\r\n" \ + "Content-Transfer-Encoding: base64\r\n" \ + "X-OIM-Message-Type: OfflineMessage\r\n" \ + "X-OIM-Run-Id: {89527393-8723-4F4F-8005-287532973298}\r\n" \ + "X-OIM-Sequence-Num: %d\r\n" \ + "\r\n" \ + "%s" \ + "" \ +"" \ +"" + +int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg ); + +#endif /* __SOAP_H__ */ -- cgit v1.2.3 From ffb6dea650db7671d2414b1a9541cf0baba8ff11 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 20 Mar 2010 21:58:04 +0000 Subject: Killing some memory leaks. --- protocols/msn/msn.c | 1 + protocols/msn/soap.c | 10 +++++++--- protocols/msn/soap.h | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 49ce9298..4d859346 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -100,6 +100,7 @@ static void msn_logout( struct im_connection *ic ) g_free( md->grouplist ); g_free( md->passport_token ); + g_free( md->lock_key ); g_free( md ); } diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index d3a022ec..f329cea9 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -102,6 +102,8 @@ static int msn_soap_send_request( struct msn_soap_req_data *soap_req ) soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS, http_req, msn_soap_handle_response, soap_req ); + g_free( http_req ); + return soap_req->http_req != NULL; } @@ -122,14 +124,16 @@ static void msn_soap_handle_response( struct http_request *http_req ) st = soap_req->handle_response( soap_req ); + g_free( soap_req->url ); + g_free( soap_req->action ); + g_free( soap_req->payload ); + soap_req->url = soap_req->action = soap_req->payload = NULL; + if( st == MSN_SOAP_RETRY && --soap_req->ttl ) msn_soap_send_request( soap_req ); else { soap_req->free_data( soap_req ); - g_free( soap_req->url ); - g_free( soap_req->action ); - g_free( soap_req->payload ); g_free( soap_req ); } } diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 4e7d6627..687cc282 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -68,7 +68,8 @@ "" \ "" \ "text" \ - "MIME-Version: 1.0\r\n" \ + "" \ + "MIME-Version: 1.0\r\n" \ "Content-Type: text/plain; charset=UTF-8\r\n" \ "Content-Transfer-Encoding: base64\r\n" \ "X-OIM-Message-Type: OfflineMessage\r\n" \ -- cgit v1.2.3 From bc090f0c3bc243de277a8e04f906384838d95e35 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 20 Mar 2010 22:42:59 +0000 Subject: Error reporting and added a msgq_send function. Need to put some more intelligence into it later. --- protocols/msn/sb.c | 16 +++++----------- protocols/msn/soap.c | 54 +++++++++++++++++++++++++++++++++++++++++++--------- protocols/msn/soap.h | 1 + 3 files changed, 51 insertions(+), 20 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 920e7f61..461bd483 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -606,18 +606,12 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) int num = atoi( cmd[0] ); const struct msn_status_code *err = msn_status_by_number( num ); + /* If the person is offline, send an offline message instead, + and don't report an error. */ if( num == 217 ) - { - GSList *l; - - for( l = sb->msgq; l; l = l->next ) - { - struct msn_message *m = l->data; - msn_soap_oim_send( ic, m->who, m->text ); - } - } - - imcb_error( ic, "Error reported by switchboard server: %s", err->text ); + msn_soap_oim_send_queue( ic, &sb->msgq ); + else + imcb_error( ic, "Error reported by switchboard server: %s", err->text ); if( err->flags & STATUS_SB_FATAL ) { diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index f329cea9..82ecfea2 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -56,14 +56,6 @@ struct msn_soap_req_data msn_soap_func build_request, handle_response, free_data; }; -struct msn_soap_oim_send_data -{ - char *to; - char *msg; - int number; - int need_retry; -}; - static int msn_soap_send_request( struct msn_soap_req_data *req ); static int msn_soap_start( struct im_connection *ic, @@ -138,6 +130,17 @@ static void msn_soap_handle_response( struct http_request *http_req ) } } + +/* oim_send: Sending offline messages */ + +struct msn_soap_oim_send_data +{ + char *to; + char *msg; + int number; + int need_retry; +}; + static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) { struct msn_soap_oim_send_data *oim = soap_req->data; @@ -182,15 +185,21 @@ static int msn_soap_oim_handle_response( struct msn_soap_req_data *soap_req ) { struct msn_soap_oim_send_data *oim = soap_req->data; - if( soap_req->http_req->status_code == 500 && oim->need_retry ) + if( soap_req->http_req->status_code == 500 && oim->need_retry && soap_req->ttl > 0 ) { oim->need_retry = 0; return MSN_SOAP_RETRY; } else if( soap_req->http_req->status_code == 200 ) + { + imcb_log( soap_req->ic, "Offline message successfully delivered to %s", oim->to ); return MSN_SOAP_OK; + } else + { + imcb_log( soap_req->ic, "Failed to deliver offline message to %s:\n%s", oim->to, oim->msg ); return MSN_SOAP_ABORT; + } } static int msn_soap_oim_free_data( struct msn_soap_req_data *soap_req ) @@ -218,3 +227,30 @@ int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg msn_soap_oim_handle_response, msn_soap_oim_free_data ); } + +int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ) +{ + GSList *l; + char *n = NULL; + + for( l = *msgq; l; l = l->next ) + { + struct msn_message *m = l->data; + + if( n == NULL ) + n = m->who; + if( strcmp( n, m->who ) == 0 ) + msn_soap_oim_send( ic, m->who, m->text ); + } + + while( *msgq != NULL ) + { + struct msn_message *m = (*msgq)->data; + + g_free( m->who ); + g_free( m->text ); + g_free( m ); + + *msgq = g_slist_remove( *msgq, m ); + } +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 687cc282..3db2d59d 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -82,5 +82,6 @@ "" int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg ); +int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); #endif /* __SOAP_H__ */ -- cgit v1.2.3 From 5fecede7db56a41cf9d6ecb2b821f5a833ce0f59 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 8 Aug 2010 18:29:43 +0100 Subject: Enough changes to successfully login up to (but not including) fetching the contact list. --- protocols/msn/ns.c | 12 +++++++++--- protocols/msn/sb.c | 1 + protocols/msn/soap.c | 3 ++- protocols/msn/soap.h | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 40c4cdec..897650a6 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -72,7 +72,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) 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 MSNP14 CVR0\r\n", ++md->trId ); if( msn_write( ic, s, strlen( s ) ) ) { ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); @@ -112,7 +112,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[0], "VER" ) == 0 ) { - if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 ) + if( cmd[2] && strncmp( cmd[2], "MSNP14", 5 ) != 0 ) { imcb_error( ic, "Unsupported protocol" ); imc_logout( ic, FALSE ); @@ -229,7 +229,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } } - else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 ) + else if( strcmp( cmd[2], "OK" ) == 0 ) { if( num_parts == 7 ) msn_ns_got_display_name( ic, cmd[4] ); @@ -655,6 +655,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } } } + else if( strcmp( cmd[0], "GCF" ) == 0 ) + { + /* Coming up is cmd[2] bytes of stuff we're supposed to + censore. Meh. */ + md->handler->msglen = atoi( cmd[2] ); + } else if( isdigit( cmd[0][0] ) ) { int num = atoi( cmd[0] ); diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 10425708..1eb919e3 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -29,6 +29,7 @@ #include "passport.h" #include "md5.h" #include "soap.h" +#include "invitation.h" static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ); static int msn_sb_command( gpointer data, char **cmd, int num_parts ); diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 82ecfea2..4d623a9d 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -154,7 +154,8 @@ static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) soap_req->action = g_strdup( SOAP_OIM_ACTION_URL ); soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD, ic->acc->user, display_name_b64, oim->to, md->passport_token, - MSNP11_PROD_ID, md->lock_key ? : "", oim->number, oim->number, oim->msg ); + MSNP11_PROD_ID, md->lock_key ? md->lock_key : "", + oim->number, oim->number, oim->msg ); g_free( display_name_b64 ); diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 3db2d59d..307ac1bc 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -73,7 +73,7 @@ "Content-Type: text/plain; charset=UTF-8\r\n" \ "Content-Transfer-Encoding: base64\r\n" \ "X-OIM-Message-Type: OfflineMessage\r\n" \ - "X-OIM-Run-Id: {89527393-8723-4F4F-8005-287532973298}\r\n" \ + "X-OIM-Run-Id: {F9A6C9DD-0D94-4E85-9CC6-F9D118CC1CAF}\r\n" \ "X-OIM-Sequence-Num: %d\r\n" \ "\r\n" \ "%s" \ -- cgit v1.2.3 From 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 9 Aug 2010 20:04:55 +0100 Subject: Not working yet, but some code for fetching the membership list. Apparently an upgrade to MSNP15 is needed. Oh well. --- protocols/msn/ns.c | 4 ++-- protocols/msn/soap.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++-- protocols/msn/soap.h | 29 ++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 5 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 897650a6..8236b731 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -28,6 +28,7 @@ #include "msn.h" #include "passport.h" #include "md5.h" +#include "soap.h" static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); static int msn_ns_command( gpointer data, char **cmd, int num_parts ); @@ -238,8 +239,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imcb_log( ic, "Authenticated, getting buddy list" ); - g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId ); - return( msn_write( ic, buf, strlen( buf ) ) ); + msn_soap_memlist_request( ic ); } else { diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 4d623a9d..252bddeb 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -82,14 +82,22 @@ static void msn_soap_handle_response( struct http_request *http_req ); static int msn_soap_send_request( struct msn_soap_req_data *soap_req ) { + struct msn_data *md = soap_req->ic->proto_data; char *http_req; + char *pom, *s; url_t url; soap_req->build_request( soap_req ); + pom = g_new0( char, strlen( md->passport_token ) * 3 ); + strcpy( pom, md->passport_token + 2 ); + if( ( s = strchr( pom, '&' ) ) ) + *s = '\0'; + url_set( &url, soap_req->url ); http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host, - soap_req->action, strlen( soap_req->payload ), soap_req->payload ); + soap_req->action, pom, + strlen( soap_req->payload ), soap_req->payload ); soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS, http_req, msn_soap_handle_response, soap_req ); @@ -151,7 +159,7 @@ static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) display_name_b64 = tobase64( ic->displayname ); soap_req->url = g_strdup( SOAP_OIM_SEND_URL ); - soap_req->action = g_strdup( SOAP_OIM_ACTION_URL ); + soap_req->action = g_strdup( SOAP_OIM_SEND_ACTION ); soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD, ic->acc->user, display_name_b64, oim->to, md->passport_token, MSNP11_PROD_ID, md->lock_key ? md->lock_key : "", @@ -255,3 +263,47 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ) *msgq = g_slist_remove( *msgq, m ); } } + + +/* memlist: Fetching the membership list (NOT address book) */ + +#if 0 +struct msn_soap_oim_send_data +{ + char *to; + char *msg; + int number; + int need_retry; +}; +#endif + +static int msn_soap_memlist_build_request( struct msn_soap_req_data *soap_req ) +{ + soap_req->url = g_strdup( SOAP_MEMLIST_URL ); + soap_req->action = g_strdup( SOAP_MEMLIST_ACTION ); + soap_req->payload = g_strdup( SOAP_MEMLIST_PAYLOAD ); + + return 1; +} + +static const struct xt_handler_entry msn_soap_memlist_parser[] = { + { NULL, NULL, NULL } +}; + +static int msn_soap_memlist_handle_response( struct msn_soap_req_data *soap_req ) +{ + return 0; +} + +static int msn_soap_memlist_free_data( struct msn_soap_req_data *soap_req ) +{ + return 0; +} + +int msn_soap_memlist_request( struct im_connection *ic ) +{ + return msn_soap_start( ic, NULL, msn_soap_memlist_build_request, + msn_soap_memlist_parser, + msn_soap_memlist_handle_response, + msn_soap_memlist_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 307ac1bc..78808fdf 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -45,6 +45,7 @@ "SOAPAction: \"%s\"\r\n" \ "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ "Content-Type: text/xml; charset=utf-8\r\n" \ +"Cookie: MSPAuth=%s\r\n" \ "Content-Length: %d\r\n" \ "Cache-Control: no-cache\r\n" \ "\r\n" \ @@ -52,7 +53,7 @@ #define SOAP_OIM_SEND_URL "https://ows.messenger.msn.com/OimWS/oim.asmx" -#define SOAP_OIM_ACTION_URL "http://messenger.msn.com/ws/2004/09/oim/Store" +#define SOAP_OIM_SEND_ACTION "http://messenger.msn.com/ws/2004/09/oim/Store" #define SOAP_OIM_SEND_PAYLOAD \ "" \ @@ -84,4 +85,30 @@ int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg ); int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); + +#define SOAP_MEMLIST_URL "https://byrdr.omega.contacts.msn.com/abservice/SharingService.asmx" +#define SOAP_MEMLIST_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership" + +#define SOAP_MEMLIST_PAYLOAD \ +"" \ +"" \ + "" \ + "" \ + "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ + "false" \ + "Initial" \ + "" \ + "" \ + "false" \ + "" \ + "" \ + "" \ + "MessengerInvitationSocialNetworkSpaceProfile" \ + "" \ + "" \ +"" + +int msn_soap_memlist_request( struct im_connection *ic ); + + #endif /* __SOAP_H__ */ -- cgit v1.2.3 From 523fb2324a351e9607ad2a803c6e866c5175aa16 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 11 Aug 2010 09:08:39 +0100 Subject: Implement MSNP15 SSO (Sadistic Sign-On). --- protocols/msn/Makefile | 2 +- protocols/msn/msn.c | 3 +- protocols/msn/msn.h | 3 +- protocols/msn/msn_util.c | 41 +++++------ protocols/msn/ns.c | 32 +++------ protocols/msn/sb.c | 6 ++ protocols/msn/soap.c | 175 ++++++++++++++++++++++++++++++++++++++++++++--- protocols/msn/soap.h | 71 ++++++++++++++++++- 8 files changed, 269 insertions(+), 64 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index b9c7ed28..28fe81c9 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -42,4 +42,4 @@ msn_mod.o: $(objects) @echo '*' Linking msn_mod.o @$(LD) $(LFLAGS) $(objects) -o msn_mod.o - +soap.o: soap.h soap.c diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 6222e1b6..10c27a1d 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -102,7 +102,8 @@ static void msn_logout( struct im_connection *ic ) while( md->groupcount > 0 ) g_free( md->grouplist[--md->groupcount] ); g_free( md->grouplist ); - g_free( md->passport_token ); + g_free( md->tokens[0] ); + g_free( md->tokens[1] ); g_free( md->lock_key ); while( md->grpq ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index f060000a..d4f3442e 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -75,7 +75,7 @@ struct msn_data struct msn_handler_data *handler; int trId; - char *passport_token; + char *tokens[2]; char *lock_key; GSList *msgq, *grpq; @@ -170,6 +170,7 @@ extern GSList *msn_switchboards; /* ns.c */ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); +void msn_auth_got_passport_token( struct im_connection *ic, char *token ); /* msn_util.c */ int msn_write( struct im_connection *ic, char *s, int len ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 954ee716..65b12476 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -33,6 +33,12 @@ int msn_write( struct im_connection *ic, char *s, int len ) struct msn_data *md = ic->proto_data; int st; + if( getenv( "BITLBEE_DEBUG" ) ) + { + write( 2, "->NS:", 5 ); + write( 2, s, len ); + } + st = write( md->fd, s, len ); if( st != len ) { @@ -280,6 +286,12 @@ int msn_handler( struct msn_handler_data *h ) if( st <= 0 ) return( -1 ); + if( getenv( "BITLBEE_DEBUG" ) ) + { + write( 2, "->C:", 4 ); + write( 2, h->rxq + h->rxlen - st, st ); + } + while( st ) { int i; @@ -445,27 +457,6 @@ gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ) return msn_write( ic, buf, strlen( buf ) ) != 0; } -unsigned int little_endian( unsigned int dw ) -{ -#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN - return dw; -#else - /* We're still not sure if this machine is big endian since the - constants above are not that portable. Don't swap bytes, just - force-compose a 32-bit little endian integer. */ - unsigned int ret = 0, i; - char *dst = (char*) (&ret + 1); - - for (i = 0; i < 4; i ++) - { - *(--dst) = dw >> 24; - dw <<= 8; - } - - return ret; -#endif -} - /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ char *msn_p11_challenge( char *challenge ) { @@ -486,7 +477,7 @@ char *msn_p11_challenge( char *challenge ) md5Parts = (unsigned int *)md5Hash; for (i = 0; i < 4; i ++) { - md5Parts[i] = little_endian(md5Parts[i]); + md5Parts[i] = GUINT32_TO_LE(md5Parts[i]); /* & each integer with 0x7FFFFFFF */ /* and save one unmodified array for later */ @@ -507,8 +498,8 @@ char *msn_p11_challenge( char *challenge ) { long long temp; - chlStringParts[i] = little_endian(chlStringParts[i]); - chlStringParts[i+1] = little_endian(chlStringParts[i+1]); + chlStringParts[i] = GUINT32_TO_LE(chlStringParts[i]); + chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]); temp = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF; nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF; @@ -524,7 +515,7 @@ char *msn_p11_challenge( char *challenge ) /* swap more bytes if big endian */ for (i = 0; i < 4; i ++) - newHashParts[i] = little_endian(newHashParts[i]); + newHashParts[i] = GUINT32_TO_LE(newHashParts[i]); /* make a string of the parts */ newHash = (unsigned char *)newHashParts; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 8236b731..f0d6a58d 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -34,7 +34,6 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); -static void msn_auth_got_passport_token( struct msn_auth_data *mad ); static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) @@ -73,7 +72,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) md->handler->fd = md->fd; md->handler->rxq = g_new0( char, 1 ); - g_snprintf( s, sizeof( s ), "VER %d MSNP14 CVR0\r\n", ++md->trId ); + g_snprintf( s, sizeof( s ), "VER %d MSNP15 CVR0\r\n", ++md->trId ); if( msn_write( ic, s, strlen( s ) ) ) { ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); @@ -113,7 +112,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[0], "VER" ) == 0 ) { - if( cmd[2] && strncmp( cmd[2], "MSNP14", 5 ) != 0 ) + if( cmd[2] && strncmp( cmd[2], "MSNP15", 5 ) != 0 ) { imcb_error( ic, "Unsupported protocol" ); imc_logout( ic, FALSE ); @@ -127,7 +126,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) else if( strcmp( cmd[0], "CVR" ) == 0 ) { /* We don't give a damn about the information we just received */ - g_snprintf( buf, sizeof( buf ), "USR %d TWN I %s\r\n", ++md->trId, ic->acc->user ); + g_snprintf( buf, sizeof( buf ), "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); return( msn_write( ic, buf, strlen( buf ) ) ); } else if( strcmp( cmd[0], "XFR" ) == 0 ) @@ -220,15 +219,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "USR" ) == 0 ) { - if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) + if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 && + strcmp( cmd[3], "S" ) == 0 ) { - /* Time for some Passport black magic... */ - if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) - { - imcb_error( ic, "Error while contacting Passport server" ); - imc_logout( ic, TRUE ); - return( 0 ); - } + msn_soap_passport_sso_request( ic, cmd[4], cmd[5] ); } else if( strcmp( cmd[2], "OK" ) == 0 ) { @@ -774,9 +768,8 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int return( 1 ); } -static void msn_auth_got_passport_token( struct msn_auth_data *mad ) +void msn_auth_got_passport_token( struct im_connection *ic, char *token ) { - struct im_connection *ic = mad->data; struct msn_data *md; /* Dead connection? */ @@ -784,20 +777,13 @@ static void msn_auth_got_passport_token( struct msn_auth_data *mad ) return; md = ic->proto_data; - if( mad->token ) + { char buf[1024]; - md->passport_token = g_strdup( mad->token ); - - g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token ); + g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); msn_write( ic, buf, strlen( buf ) ); } - else - { - imcb_error( ic, "Error during Passport authentication: %s", mad->error ); - imc_logout( ic, TRUE ); - } } static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ) diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 1eb919e3..07e94072 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -39,6 +39,12 @@ int msn_sb_write( struct msn_switchboard *sb, char *s, int len ) { int st; + if( getenv( "BITLBEE_DEBUG" ) ) + { + write( 2, "->SB:", 5 ); + write( 2, s, len ); + } + st = write( sb->fd, s, len ); if( st != len ) { diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 252bddeb..e837986e 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -27,6 +27,7 @@ #include "bitlbee.h" #include "url.h" #include "misc.h" +#include "sha1.h" #include "base64.h" #include "xmltree.h" #include @@ -82,27 +83,25 @@ static void msn_soap_handle_response( struct http_request *http_req ); static int msn_soap_send_request( struct msn_soap_req_data *soap_req ) { - struct msn_data *md = soap_req->ic->proto_data; char *http_req; - char *pom, *s; + char *soap_action = NULL; url_t url; soap_req->build_request( soap_req ); - pom = g_new0( char, strlen( md->passport_token ) * 3 ); - strcpy( pom, md->passport_token + 2 ); - if( ( s = strchr( pom, '&' ) ) ) - *s = '\0'; + if( soap_req->action ) + soap_action = g_strdup_printf( "SOAPAction: \"%s\"\r\n", soap_req->action ); url_set( &url, soap_req->url ); http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host, - soap_req->action, pom, + soap_action ? soap_action : "", strlen( soap_req->payload ), soap_req->payload ); soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS, http_req, msn_soap_handle_response, soap_req ); g_free( http_req ); + g_free( soap_action ); return soap_req->http_req != NULL; } @@ -139,6 +138,160 @@ static void msn_soap_handle_response( struct http_request *http_req ) } +/* passport_sso: Authentication MSNP15+ */ + +struct msn_soap_passport_sso_data +{ + char *policy; + char *nonce; + char *secret; +}; + +static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_soap_passport_sso_data *sd = soap_req->data; + struct im_connection *ic = soap_req->ic; + + soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL ); + soap_req->payload = g_markup_printf_escaped( SOAP_PASSPORT_SSO_PAYLOAD, + ic->acc->user, ic->acc->pass, sd->policy ); + + return MSN_SOAP_OK; +} + +static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer data ) +{ + struct msn_soap_req_data *soap_req = data; + struct msn_soap_passport_sso_data *sd = soap_req->data; + struct msn_data *md = soap_req->ic->proto_data; + struct xt_node *p; + char *id; + + if( ( id = xt_find_attr( node, "Id" ) ) == NULL ) + return XT_HANDLED; + id += strlen( id ) - 1; + if( *id == '1' && + ( p = node->parent ) && ( p = p->parent ) && + ( p = xt_find_node( p->children, "wst:RequestedProofToken" ) ) && + ( p = xt_find_node( p->children, "wst:BinarySecret" ) ) && + p->text ) + sd->secret = g_strdup( p->text ); + + if( *id == '1' ) + md->tokens[0] = g_strdup( node->text ); + else if( *id == '2' ) + md->tokens[1] = g_strdup( node->text ); + + return XT_HANDLED; +} + +static const struct xt_handler_entry msn_soap_passport_sso_parser[] = { + { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", msn_soap_passport_sso_token }, + { NULL, NULL, NULL } +}; + +static char *msn_key_fuckery( char *key, int key_len, char *type ) +{ + unsigned char hash1[20+strlen(type)+1]; + unsigned char hash2[20]; + char *ret; + + sha1_hmac( key, key_len, type, 0, hash1 ); + strcpy( (char*) hash1 + 20, type ); + sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash2 ); + + /* This is okay as hash1 is read completely before it's overwritten. */ + sha1_hmac( key, key_len, (char*) hash1, 20, hash1 ); + sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash1 ); + + ret = g_malloc( 24 ); + memcpy( ret, hash2, 20 ); + memcpy( ret + 20, hash1, 4 ); + return ret; +} + +static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap_req ) +{ + struct msn_soap_passport_sso_data *sd = soap_req->data; + struct im_connection *ic = soap_req->ic; + char *key1, *key2, *key3, *blurb64; + int key1_len; + unsigned char *padnonce, *des3res; + struct + { + unsigned int uStructHeaderSize; // 28. Does not count data + unsigned int uCryptMode; // CRYPT_MODE_CBC (1) + unsigned int uCipherType; // TripleDES (0x6603) + unsigned int uHashType; // SHA1 (0x8004) + unsigned int uIVLen; // 8 + unsigned int uHashLen; // 20 + unsigned int uCipherLen; // 72 + unsigned char iv[8]; + unsigned char hash[20]; + unsigned char cipherbytes[72]; + } blurb = { + GUINT32_TO_LE( 28 ), + GUINT32_TO_LE( 1 ), + GUINT32_TO_LE( 0x6603 ), + GUINT32_TO_LE( 0x8004 ), + GUINT32_TO_LE( 8 ), + GUINT32_TO_LE( 20 ), + GUINT32_TO_LE( 72 ), + }; + + key1_len = base64_decode( sd->secret, (unsigned char**) &key1 ); + + key2 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY HASH" ); + key3 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY ENCRYPTION" ); + + sha1_hmac( key2, 24, sd->nonce, 0, blurb.hash ); + padnonce = g_malloc( strlen( sd->nonce ) + 8 ); + strcpy( (char*) padnonce, sd->nonce ); + memset( padnonce + strlen( sd->nonce ), 8, 8 ); + + random_bytes( blurb.iv, 8 ); + + ssl_des3_encrypt( (unsigned char*) key3, 24, padnonce, strlen( sd->nonce ) + 8, blurb.iv, &des3res ); + memcpy( blurb.cipherbytes, des3res, 72 ); + + blurb64 = base64_encode( (unsigned char*) &blurb, sizeof( blurb ) ); + msn_auth_got_passport_token( ic, blurb64 ); + + g_free( padnonce ); + g_free( blurb64 ); + g_free( des3res ); + g_free( key1 ); + g_free( key2 ); + g_free( key3 ); + + return MSN_SOAP_OK; +} + +static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req ) +{ + struct msn_soap_passport_sso_data *sd = soap_req->data; + + g_free( sd->policy ); + g_free( sd->nonce ); + g_free( sd->secret ); + + return MSN_SOAP_OK; +} + +int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce ) +{ + struct msn_soap_passport_sso_data *sd = g_new0( struct msn_soap_passport_sso_data, 1 ); + + sd->policy = g_strdup( policy ); + sd->nonce = g_strdup( nonce ); + + return msn_soap_start( ic, sd, msn_soap_passport_sso_build_request, + msn_soap_passport_sso_parser, + msn_soap_passport_sso_handle_response, + msn_soap_passport_sso_free_data ); +} + + /* oim_send: Sending offline messages */ struct msn_soap_oim_send_data @@ -161,13 +314,13 @@ static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) soap_req->url = g_strdup( SOAP_OIM_SEND_URL ); soap_req->action = g_strdup( SOAP_OIM_SEND_ACTION ); soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD, - ic->acc->user, display_name_b64, oim->to, md->passport_token, + ic->acc->user, display_name_b64, oim->to, "bla", //md->passport_token, MSNP11_PROD_ID, md->lock_key ? md->lock_key : "", oim->number, oim->number, oim->msg ); g_free( display_name_b64 ); - return 1; + return MSN_SOAP_OK; } static xt_status msn_soap_oim_send_challenge( struct xt_node *node, gpointer data ) @@ -219,7 +372,7 @@ static int msn_soap_oim_free_data( struct msn_soap_req_data *soap_req ) g_free( oim->msg ); g_free( oim ); - return 0; + return MSN_SOAP_OK; } int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg ) @@ -262,6 +415,8 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ) *msgq = g_slist_remove( *msgq, m ); } + + return 1; } diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 78808fdf..5fbac3c4 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -42,16 +42,81 @@ "POST %s HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Accept: */*\r\n" \ -"SOAPAction: \"%s\"\r\n" \ "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ "Content-Type: text/xml; charset=utf-8\r\n" \ -"Cookie: MSPAuth=%s\r\n" \ -"Content-Length: %d\r\n" \ +"%s" \ +"Content-Length: %zd\r\n" \ "Cache-Control: no-cache\r\n" \ "\r\n" \ "%s" +#define SOAP_PASSPORT_SSO_URL "https://login.live.com/RST.srf" +#define SOAP_PASSPORT_SSO_URL_MSN "https://msnia.login.live.com/pp550/RST.srf" + +#define SOAP_PASSPORT_SSO_PAYLOAD \ +"" \ + "
" \ + "" \ + "{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}" \ + "4" \ + "1" \ + "" \ + "AQAAAAIAAABsYwQAAAAxMDMz" \ + "" \ + "" \ + "" \ + "%s" \ + "%s" \ + "" \ + "" \ + "
" \ + "" \ + "" \ + "" \ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ + "" \ + "" \ + "http://Passport.NET/tb" \ + "" \ + "" \ + "" \ + "" \ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ + "" \ + "" \ + "messengerclear.live.com" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ + "" \ + "" \ + "contacts.msn.com" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ +"
" + +int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce ); + + #define SOAP_OIM_SEND_URL "https://ows.messenger.msn.com/OimWS/oim.asmx" #define SOAP_OIM_SEND_ACTION "http://messenger.msn.com/ws/2004/09/oim/Store" -- cgit v1.2.3 From 7f34ce254c1a1587e5560456dd11acb29345206d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 12 Aug 2010 00:03:33 +0100 Subject: Get contact list/address book info. Next step: We have to send it back. Seriously. Wish I were joking. --- protocols/msn/msn.c | 13 +++++ protocols/msn/msn.h | 15 +++++ protocols/msn/soap.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++---- protocols/msn/soap.h | 33 ++++++++++- 4 files changed, 202 insertions(+), 13 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 10c27a1d..0b9cffc2 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -333,6 +333,16 @@ static char *set_eval_display_name( set_t *set, char *value ) return msn_set_display_name( ic, value ) ? value : NULL; } +static void msn_buddy_data_add( bee_user_t *bu ) +{ + bu->data = g_new0( struct msn_buddy_data, 1 ); +} + +static void msn_buddy_data_free( bee_user_t *bu ) +{ + g_free( bu->data ); +} + void msn_initmodule() { struct prpl *ret = g_new0(struct prpl, 1); @@ -359,6 +369,9 @@ void msn_initmodule() ret->rem_deny = msn_rem_deny; ret->send_typing = msn_send_typing; ret->handle_cmp = g_strcasecmp; + ret->buddy_data_add = msn_buddy_data_add; + ret->buddy_data_free = msn_buddy_data_free; + //ret->transfer_request = msn_ftp_transfer_request; register_protocol(ret); diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index d4f3442e..757359fe 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -150,6 +150,21 @@ struct msn_handler_data int (*exec_message) ( gpointer data, char *msg, int msglen, char **cmd, int count ); }; +typedef enum +{ + MSN_BUDDY_FL = 1, + MSN_BUDDY_AL = 2, + MSN_BUDDY_BL = 4, + MSN_BUDDY_RL = 8, + MSN_BUDDY_PL = 16, +} msn_buddy_flags_t; + +struct msn_buddy_data +{ + char *cid; + msn_buddy_flags_t flags; +}; + /* Bitfield values for msn_status_code.flags */ #define STATUS_FATAL 1 #define STATUS_SB_FATAL 2 diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index e837986e..62d58200 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -422,32 +422,61 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ) /* memlist: Fetching the membership list (NOT address book) */ -#if 0 -struct msn_soap_oim_send_data -{ - char *to; - char *msg; - int number; - int need_retry; -}; -#endif - static int msn_soap_memlist_build_request( struct msn_soap_req_data *soap_req ) { + struct msn_data *md = soap_req->ic->proto_data; + soap_req->url = g_strdup( SOAP_MEMLIST_URL ); soap_req->action = g_strdup( SOAP_MEMLIST_ACTION ); - soap_req->payload = g_strdup( SOAP_MEMLIST_PAYLOAD ); + soap_req->payload = g_markup_printf_escaped( SOAP_MEMLIST_PAYLOAD, md->tokens[1] ); return 1; } +static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) +{ + bee_user_t *bu; + struct msn_buddy_data *bd; + struct xt_node *p; + char *role = NULL, *handle = NULL; + struct msn_soap_req_data *soap_req = data; + struct im_connection *ic = soap_req->ic; + + if( ( p = node->parent ) && ( p = p->parent ) && + ( p = xt_find_node( p->children, "MemberRole" ) ) ) + role = p->text; + + if( ( p = xt_find_node( node->children, "PassportName" ) ) ) + handle = p->text; + + if( !role || !handle || + !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || + ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) ) + return XT_HANDLED; + + bd = bu->data; + if( strcmp( role, "Allow" ) == 0 ) + bd->flags |= MSN_BUDDY_AL; + else if( strcmp( role, "Block" ) == 0 ) + bd->flags |= MSN_BUDDY_BL; + else if( strcmp( role, "Reverse" ) == 0 ) + bd->flags |= MSN_BUDDY_RL; + else if( strcmp( role, "Pending" ) == 0 ) + bd->flags |= MSN_BUDDY_PL; + + return XT_HANDLED; +} + static const struct xt_handler_entry msn_soap_memlist_parser[] = { + { "Member", "Members", msn_soap_memlist_member }, { NULL, NULL, NULL } }; static int msn_soap_memlist_handle_response( struct msn_soap_req_data *soap_req ) { - return 0; + msn_soap_addressbook_request( soap_req->ic ); + + return MSN_SOAP_OK; } static int msn_soap_memlist_free_data( struct msn_soap_req_data *soap_req ) @@ -462,3 +491,104 @@ int msn_soap_memlist_request( struct im_connection *ic ) msn_soap_memlist_handle_response, msn_soap_memlist_free_data ); } + + +/* addressbook: Fetching the membership list (NOT address book) */ + +static int msn_soap_addressbook_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + + soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); + soap_req->action = g_strdup( SOAP_ADDRESSBOOK_ACTION ); + soap_req->payload = g_markup_printf_escaped( SOAP_ADDRESSBOOK_PAYLOAD, md->tokens[1] ); + + return 1; +} + +static xt_status msn_soap_addressbook_group( struct xt_node *node, gpointer data ) +{ + struct xt_node *p; + char *id = NULL, *name = NULL; + struct msn_soap_req_data *soap_req = data; + struct im_connection *ic = soap_req->ic; + + if( ( p = node->parent ) && + ( p = xt_find_node( p->children, "groupId" ) ) ) + id = p->text; + + if( ( p = xt_find_node( node->children, "name" ) ) ) + name = p->text; + + printf( "%s %s\n", id, name ); + + return XT_HANDLED; +} + +static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer data ) +{ + bee_user_t *bu; + struct msn_buddy_data *bd; + struct xt_node *p; + char *id = NULL, *type = NULL, *handle = NULL, *display_name = NULL; + struct msn_soap_req_data *soap_req = data; + struct im_connection *ic = soap_req->ic; + + if( ( p = node->parent ) && + ( p = xt_find_node( p->children, "contactId" ) ) ) + id = p->text; + if( ( p = xt_find_node( node->children, "contactType" ) ) ) + type = p->text; + if( ( p = xt_find_node( node->children, "passportName" ) ) ) + handle = p->text; + if( ( p = xt_find_node( node->children, "displayName" ) ) ) + display_name = p->text; + + if( type && g_strcasecmp( type, "me" ) == 0 ) + { + set_t *set = set_find( &ic->acc->set, "display_name" ); + g_free( set->value ); + set->value = g_strdup( display_name ); + + return XT_HANDLED; + } + + if( !( bu = bee_user_by_handle( ic->bee, ic, handle ) ) && + !( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) + return XT_HANDLED; + + bd = bu->data; + bd->flags |= MSN_BUDDY_FL; + g_free( bd->cid ); + bd->cid = g_strdup( id ); + + imcb_rename_buddy( ic, handle, display_name ); + + printf( "%s %s %s %s\n", id, type, handle, display_name ); + + return XT_HANDLED; +} + +static const struct xt_handler_entry msn_soap_addressbook_parser[] = { + { "contactInfo", "Contact", msn_soap_addressbook_contact }, + { "groupInfo", "Group", msn_soap_addressbook_group }, + { NULL, NULL, NULL } +}; + +static int msn_soap_addressbook_handle_response( struct msn_soap_req_data *soap_req ) +{ + return MSN_SOAP_OK; +} + +static int msn_soap_addressbook_free_data( struct msn_soap_req_data *soap_req ) +{ + return 0; +} + +int msn_soap_addressbook_request( struct im_connection *ic ) +{ + return msn_soap_start( ic, NULL, msn_soap_addressbook_build_request, + msn_soap_addressbook_parser, + msn_soap_addressbook_handle_response, + msn_soap_addressbook_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 5fbac3c4..9eb1caef 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -151,7 +151,7 @@ int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); -#define SOAP_MEMLIST_URL "https://byrdr.omega.contacts.msn.com/abservice/SharingService.asmx" +#define SOAP_MEMLIST_URL "http://contacts.msn.com/abservice/SharingService.asmx" #define SOAP_MEMLIST_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership" #define SOAP_MEMLIST_PAYLOAD \ @@ -165,6 +165,7 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); "" \ "" \ "false" \ + "%s" \ "" \ "" \ "" \ @@ -176,4 +177,34 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); int msn_soap_memlist_request( struct im_connection *ic ); +#define SOAP_ADDRESSBOOK_URL "http://contacts.msn.com/abservice/abservice.asmx" +#define SOAP_ADDRESSBOOK_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll" + +#define SOAP_ADDRESSBOOK_PAYLOAD \ +"" \ +"" \ + "" \ + "" \ + "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ + "false" \ + "Initial" \ + "" \ + "" \ + "false" \ + "%s" \ + "" \ + "" \ + "" \ + "" \ + "00000000-0000-0000-0000-000000000000" \ + "Full" \ + "false" \ + "0001-01-01T00:00:00.0000000-08:00" \ + "" \ + "" \ +"" + +int msn_soap_addressbook_request( struct im_connection *ic ); + + #endif /* __SOAP_H__ */ -- cgit v1.2.3 From ca7de3ac72f0ef10613badecb7eb6cc9a10f996b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 12 Aug 2010 23:13:26 +0100 Subject: Successful login (including contact list sync). \o/ --- protocols/msn/msn.c | 8 ++ protocols/msn/msn.h | 5 +- protocols/msn/msn_util.c | 12 +++ protocols/msn/ns.c | 200 +++++++++++++++++++++++------------------------ protocols/msn/soap.c | 1 + 5 files changed, 125 insertions(+), 101 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 0b9cffc2..4de2d822 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -67,6 +67,7 @@ static void msn_login( account_t *acc ) md->ic = ic; md->away_state = msn_away_state_list; + md->domaintree = g_tree_new( msn_domaintree_cmp ); msn_connections = g_slist_append( msn_connections, ic ); } @@ -106,6 +107,9 @@ static void msn_logout( struct im_connection *ic ) g_free( md->tokens[1] ); g_free( md->lock_key ); + g_tree_destroy( md->domaintree ); + md->domaintree = NULL; + while( md->grpq ) { struct msn_groupadd *ga = md->grpq->data; @@ -335,11 +339,15 @@ static char *set_eval_display_name( set_t *set, char *value ) static void msn_buddy_data_add( bee_user_t *bu ) { + struct msn_data *md = bu->ic->proto_data; bu->data = g_new0( struct msn_buddy_data, 1 ); + g_tree_insert( md->domaintree, bu->handle, bu ); } static void msn_buddy_data_free( bee_user_t *bu ) { + struct msn_data *md = bu->ic->proto_data; + g_tree_remove( md->domaintree, bu->handle ); g_free( bu->data ); } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 757359fe..6e447d7f 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -88,6 +88,7 @@ struct msn_data int buddycount; int groupcount; char **grouplist; + GTree *domaintree; }; struct msn_switchboard @@ -152,7 +153,7 @@ struct msn_handler_data typedef enum { - MSN_BUDDY_FL = 1, + MSN_BUDDY_FL = 1, /* Warning: FL,AL,BL *must* be 1,2,4. */ MSN_BUDDY_AL = 2, MSN_BUDDY_BL = 4, MSN_BUDDY_RL = 8, @@ -186,6 +187,7 @@ extern GSList *msn_switchboards; /* ns.c */ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); void msn_auth_got_passport_token( struct im_connection *ic, char *token ); +void msn_auth_got_contact_list( struct im_connection *ic ); /* msn_util.c */ int msn_write( struct im_connection *ic, char *s, int len ); @@ -200,6 +202,7 @@ char *msn_http_encode( const char *input ); void msn_msgq_purge( struct im_connection *ic, GSList **list ); gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ); char *msn_p11_challenge( char *challenge ); +gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 65b12476..3a19d92f 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -527,3 +527,15 @@ char *msn_p11_challenge( char *challenge ) return output; } + +gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ) +{ + const char *a = a_, *b = b_; + gint ret; + + if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) || + ( ret = strcmp( a, b ) ) == 0 ) + ret = strcmp( a_, b_ ); + + return ret; +} diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index f0d6a58d..ffb21c47 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -26,15 +26,16 @@ #include #include "nogaim.h" #include "msn.h" -#include "passport.h" #include "md5.h" #include "soap.h" +#include "xmltree.h" static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); +static void msn_ns_send_adl( struct im_connection *ic ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { @@ -134,7 +135,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) char *server; int port; - if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 ) + if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 ) { b_event_remove( ic->inpa ); ic->inpa = 0; @@ -155,7 +156,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) md->fd = proxy_connect( server, port, msn_ns_connected, ic ); } - else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 ) + else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 ) { struct msn_switchboard *sb; @@ -260,109 +261,34 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } } - else if( strcmp( cmd[0], "SYN" ) == 0 ) + else if( strcmp( cmd[0], "BLP" ) == 0 ) { - if( num_parts == 5 ) - { - int i, groupcount; - - groupcount = atoi( cmd[4] ); - if( groupcount > 0 ) - { - /* valgrind says this is leaking memory, I'm guessing - that this happens during server redirects. */ - if( md->grouplist ) - { - for( i = 0; i < md->groupcount; i ++ ) - g_free( md->grouplist[i] ); - g_free( md->grouplist ); - } - - md->groupcount = groupcount; - md->grouplist = g_new0( char *, md->groupcount ); - } - - md->buddycount = atoi( cmd[3] ); - if( !*cmd[3] || md->buddycount == 0 ) - msn_logged_in( ic ); - } - else - { - /* Hrrm... This SYN reply doesn't really look like something we expected. - Let's assume everything is okay. */ - - msn_logged_in( ic ); - } + msn_ns_send_adl( ic ); } - else if( strcmp( cmd[0], "LST" ) == 0 ) + else if( strcmp( cmd[0], "ADL" ) == 0 ) { - int list; - - if( num_parts != 4 && num_parts != 5 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - - http_decode( cmd[2] ); - list = atoi( cmd[3] ); - - if( list & 1 ) /* FL */ + if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 ) { - char *group = NULL; - int num; + char buf[1024]; + char *fn_raw = set_getstr( &ic->acc->set, "display_name" ); + char *fn; - if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount ) - group = md->grouplist[num]; + if( fn_raw == NULL ) + fn_raw = ic->acc->user; + fn = g_malloc( strlen( fn_raw ) * 3 + 1 ); + strcpy( fn, fn_raw ); + http_encode( fn ); - imcb_add_buddy( ic, cmd[1], group ); - imcb_rename_buddy( ic, cmd[1], cmd[2] ); - } - if( list & 2 ) /* AL */ - { - ic->permit = g_slist_append( ic->permit, g_strdup( cmd[1] ) ); - } - if( list & 4 ) /* BL */ - { - ic->deny = g_slist_append( ic->deny, g_strdup( cmd[1] ) ); - } - if( list & 8 ) /* RL */ - { - if( ( list & 6 ) == 0 ) - msn_buddy_ask( ic, cmd[1], cmd[2] ); - } - - if( --md->buddycount == 0 ) - { - if( ic->flags & OPT_LOGGED_IN ) - { - imcb_log( ic, "Successfully transferred to different server" ); - g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 ); - return( msn_write( ic, buf, strlen( buf ) ) ); - } - else - { - msn_logged_in( ic ); - } + g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", + ++md->trId, fn ); + g_free( fn ); + + msn_write( ic, buf, strlen( buf ) ); } } - else if( strcmp( cmd[0], "LSG" ) == 0 ) + else if( strcmp( cmd[0], "PRP" ) == 0 ) { - int num; - - if( num_parts != 4 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - - http_decode( cmd[2] ); - num = atoi( cmd[1] ); - - if( num < md->groupcount ) - md->grouplist[num] = g_strdup( cmd[2] ); + imcb_connected( ic ); } else if( strcmp( cmd[0], "CHL" ) == 0 ) { @@ -392,15 +318,15 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { const struct msn_away_state *st; - if( num_parts != 6 ) + if( num_parts < 6 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } - http_decode( cmd[4] ); - imcb_rename_buddy( ic, cmd[3], cmd[4] ); + http_decode( cmd[5] ); + imcb_rename_buddy( ic, cmd[3], cmd[5] ); st = msn_away_state_by_code( cmd[2] ); if( !st ) @@ -786,6 +712,80 @@ void msn_auth_got_passport_token( struct im_connection *ic, char *token ) } } +void msn_auth_got_contact_list( struct im_connection *ic ) +{ + char buf[64]; + struct msn_data *md; + + /* Dead connection? */ + if( g_slist_find( msn_connections, ic ) == NULL ) + return; + + md = ic->proto_data; + + + g_snprintf( buf, sizeof( buf ), "BLP %d %s\r\n", ++md->trId, "BL" ); + msn_write( ic, buf, strlen( buf ) ); +} + +static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) +{ + struct xt_node *adl = data, *d, *c; + struct bee_user *bu = value; + struct msn_buddy_data *bd = bu->data; + char handle[strlen(bu->handle)]; + char *domain; + char l[4]; + + strcpy( handle, bu->handle ); + if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */ + return FALSE; + *domain = '\0'; + domain ++; + + if( ( d = adl->children ) == NULL || + g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 ) + { + d = xt_new_node( "d", NULL, NULL ); + xt_add_attr( d, "n", domain ); + xt_insert_child( adl, d ); + } + + g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 ); + c = xt_new_node( "c", NULL, NULL ); + xt_add_attr( c, "n", handle ); + xt_add_attr( c, "l", l ); + xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */ + xt_insert_child( d, c ); + + return FALSE; +} + +static void msn_ns_send_adl( struct im_connection *ic ) +{ + struct xt_node *adl; + struct msn_data *md; + char *adls, buf[64]; + + /* Dead connection? */ + if( g_slist_find( msn_connections, ic ) == NULL ) + return; + + md = ic->proto_data; + + adl = xt_new_node( "ml", NULL, NULL ); + xt_add_attr( adl, "l", "1" ); + g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl ); + adls = xt_to_string( adl ); + + g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) ); + if( msn_write( ic, buf, strlen( buf ) ) ) + msn_write( ic, adls, strlen( adls ) ); + + g_free( adls ); + xt_free_node( adl ); +} + static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ) { set_t *s; diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 62d58200..bb664861 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -577,6 +577,7 @@ static const struct xt_handler_entry msn_soap_addressbook_parser[] = { static int msn_soap_addressbook_handle_response( struct msn_soap_req_data *soap_req ) { + msn_auth_got_contact_list( soap_req->ic ); return MSN_SOAP_OK; } -- cgit v1.2.3 From be7a180689ba5dc2b1cd1dc14f55c59246e238ed Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 12 Aug 2010 23:38:30 +0100 Subject: Proper responses to CHL challenges. Clean up bee_users before calling prpl->logout() since the buddy_data functions would like some structs to still exist. --- protocols/msn/msn.h | 15 +++++++++------ protocols/msn/ns.c | 25 +++++++++++++------------ protocols/nogaim.c | 16 ++++++++-------- 3 files changed, 30 insertions(+), 26 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 6e447d7f..d788260c 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -38,15 +38,18 @@ #define debug( text... ) #endif -#define QRY_NAME "msmsgs@msnmsgr.com" -#define QRY_CODE "Q1P7W2E4J9R8U3S5" - -/* This should be MSN Messenger 7.0.0813 */ -//#define MSNP11_PROD_KEY "CFHUR$52U_{VIX5T" -//#define MSNP11_PROD_ID "PROD0101{0RM?UBW" +/* This should be MSN Messenger 7.0.0813 +#define MSNP11_PROD_KEY "CFHUR$52U_{VIX5T" +#define MSNP11_PROD_ID "PROD0101{0RM?UBW" +*/ +/* Some other version. #define MSNP11_PROD_KEY "O4BG@C7BWLYQX?5G" #define MSNP11_PROD_ID "PROD01065C%ZFN6F" +*/ + +#define MSNP11_PROD_KEY "RG@XY*28Q5QHS%Q5" +#define MSNP11_PROD_ID "PROD0113H11T8$X_" #define MSN_SB_NEW -24062002 diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index ffb21c47..3e02e328 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -292,25 +292,20 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "CHL" ) == 0 ) { - md5_state_t state; - md5_byte_t digest[16]; - int i; + char *resp; - if( num_parts != 3 ) + if( num_parts < 3 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } - md5_init( &state ); - md5_append( &state, (const md5_byte_t *) cmd[2], strlen( cmd[2] ) ); - md5_append( &state, (const md5_byte_t *) QRY_CODE, strlen( QRY_CODE ) ); - md5_finish( &state, digest ); - - g_snprintf( buf, sizeof( buf ), "QRY %d %s %d\r\n", ++md->trId, QRY_NAME, 32 ); - for( i = 0; i < 16; i ++ ) - g_snprintf( buf + strlen( buf ), 3, "%02x", digest[i] ); + resp = msn_p11_challenge( cmd[2] ); + g_snprintf( buf, sizeof( buf ), "QRY %d %s %zd\r\n%s", + ++md->trId, MSNP11_PROD_ID, + strlen( resp ), resp ); + g_free( resp ); return( msn_write( ic, buf, strlen( buf ) ) ); } @@ -581,6 +576,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) censore. Meh. */ md->handler->msglen = atoi( cmd[2] ); } + else if( strcmp( cmd[0], "UBX" ) == 0 ) + { + /* Status message. Parser coming soon. */ + if( num_parts >= 4 ) + md->handler->msglen = atoi( cmd[3] ); + } else if( isdigit( cmd[0][0] ) ) { int num = atoi( cmd[0] ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 7943e026..10ffd843 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -325,14 +325,6 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) imcb_log( ic, "Signing off.." ); - b_event_remove( ic->keepalive ); - ic->keepalive = 0; - ic->acc->prpl->logout( ic ); - b_event_remove( ic->inpa ); - - g_free( ic->away ); - ic->away = NULL; - for( l = bee->users; l; ) { bee_user_t *bu = l->data; @@ -344,6 +336,14 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) l = next; } + b_event_remove( ic->keepalive ); + ic->keepalive = 0; + ic->acc->prpl->logout( ic ); + b_event_remove( ic->inpa ); + + g_free( ic->away ); + ic->away = NULL; + query_del_by_conn( (irc_t*) ic->bee->ui_data, ic ); for( a = bee->accounts; a; a = a->next ) -- cgit v1.2.3 From b46769d05371e501800a4658a0faf82c4ccdb0dd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 12 Aug 2010 23:44:56 +0100 Subject: Some syntax checking fixups; don't make the same mistake of failing just if the MSN server is sending a little bit *more* info. And adding xt_insert_node() used in the ADL generation code. --- protocols/msn/ns.c | 16 +++++----------- protocols/msn/sb.c | 12 ++++++------ 2 files changed, 11 insertions(+), 17 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 3e02e328..2d40b47b 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -227,13 +227,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[2], "OK" ) == 0 ) { - if( num_parts == 7 ) - msn_ns_got_display_name( ic, cmd[4] ); - else - imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); - imcb_log( ic, "Authenticated, getting buddy list" ); - msn_soap_memlist_request( ic ); } else @@ -245,7 +239,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "MSG" ) == 0 ) { - if( num_parts != 4 ) + if( num_parts < 4 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); @@ -347,7 +341,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { const struct msn_away_state *st; - if( num_parts != 5 ) + if( num_parts < 5 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); @@ -376,7 +370,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) char *server; int session, port; - if( num_parts != 7 ) + if( num_parts < 7 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); @@ -420,7 +414,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "ADD" ) == 0 ) { - if( num_parts == 6 && strcmp( cmd[2], "RL" ) == 0 ) + if( num_parts >= 6 && strcmp( cmd[2], "RL" ) == 0 ) { GSList *l; @@ -484,7 +478,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) and since MSN servers can apparently screw up the formatting. */ else if( strcmp( cmd[0], "REA" ) == 0 ) { - if( num_parts != 5 ) + if( num_parts < 5 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 07e94072..b718d4e8 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -413,7 +413,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "USR" ) == 0 ) { - if( num_parts != 5 ) + if( num_parts < 5 ) { msn_sb_destroy( sb ); return( 0 ); @@ -439,7 +439,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) { int num, tot; - if( num_parts != 6 ) + if( num_parts < 6 ) { msn_sb_destroy( sb ); return( 0 ); @@ -476,7 +476,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "ANS" ) == 0 ) { - if( num_parts != 3 ) + if( num_parts < 3 ) { msn_sb_destroy( sb ); return( 0 ); @@ -495,7 +495,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "CAL" ) == 0 ) { - if( num_parts != 4 || !isdigit( cmd[3][0] ) ) + if( num_parts < 4 || !isdigit( cmd[3][0] ) ) { msn_sb_destroy( sb ); return( 0 ); @@ -505,7 +505,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "JOI" ) == 0 ) { - if( num_parts != 3 ) + if( num_parts < 3 ) { msn_sb_destroy( sb ); return( 0 ); @@ -566,7 +566,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "MSG" ) == 0 ) { - if( num_parts != 4 ) + if( num_parts < 4 ) { msn_sb_destroy( sb ); return( 0 ); -- cgit v1.2.3 From 91d6e9108bce93925a1bad60613d01c5382d003d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 13 Aug 2010 10:12:31 +0100 Subject: Sending offline messages works now ... but Pidgin doesn't seem to receive them. :-/ --- protocols/msn/msn.c | 1 + protocols/msn/msn.h | 11 ++++++++--- protocols/msn/ns.c | 4 ++-- protocols/msn/soap.c | 15 +++++++++------ protocols/msn/soap.h | 13 +++++++++++-- 5 files changed, 31 insertions(+), 13 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 4de2d822..ef70fe0c 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -105,6 +105,7 @@ static void msn_logout( struct im_connection *ic ) g_free( md->grouplist ); g_free( md->tokens[0] ); g_free( md->tokens[1] ); + g_free( md->tokens[2] ); g_free( md->lock_key ); g_tree_destroy( md->domaintree ); diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index d788260c..8abe6875 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -48,8 +48,13 @@ #define MSNP11_PROD_ID "PROD01065C%ZFN6F" */ -#define MSNP11_PROD_KEY "RG@XY*28Q5QHS%Q5" -#define MSNP11_PROD_ID "PROD0113H11T8$X_" +#define MSNP11_PROD_KEY "ILTXC!4IXB5FB*PX" +//PK}_A_0N_K%O?A9S" +#define MSNP11_PROD_ID "PROD0119GSJUC$18" +//PROD0114ES4Z%Q5W" +#define MSNP_VER "MSNP15" +#define MSNP_BUILD "8.5.1288" +//"8.1.0178" #define MSN_SB_NEW -24062002 @@ -78,7 +83,7 @@ struct msn_data struct msn_handler_data *handler; int trId; - char *tokens[2]; + char *tokens[3]; char *lock_key; GSList *msgq, *grpq; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 2d40b47b..4ae8693d 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -73,7 +73,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) md->handler->fd = md->fd; md->handler->rxq = g_new0( char, 1 ); - g_snprintf( s, sizeof( s ), "VER %d MSNP15 CVR0\r\n", ++md->trId ); + g_snprintf( s, sizeof( s ), "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ); if( msn_write( ic, s, strlen( s ) ) ) { ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); @@ -113,7 +113,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[0], "VER" ) == 0 ) { - if( cmd[2] && strncmp( cmd[2], "MSNP15", 5 ) != 0 ) + if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 ) { imcb_error( ic, "Unsupported protocol" ); imc_logout( ic, FALSE ); diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index bb664861..0fb36bb4 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -177,10 +177,12 @@ static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer dat p->text ) sd->secret = g_strdup( p->text ); - if( *id == '1' ) - md->tokens[0] = g_strdup( node->text ); - else if( *id == '2' ) - md->tokens[1] = g_strdup( node->text ); + *id -= '1'; + if( *id >= 0 && *id <= 2 ) + { + g_free( md->tokens[(int)*id] ); + md->tokens[(int)*id] = g_strdup( node->text ); + } return XT_HANDLED; } @@ -309,12 +311,13 @@ static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) struct msn_data *md = ic->proto_data; char *display_name_b64; - display_name_b64 = tobase64( ic->displayname ); + display_name_b64 = tobase64( set_getstr( &ic->acc->set, "display_name" ) ); soap_req->url = g_strdup( SOAP_OIM_SEND_URL ); soap_req->action = g_strdup( SOAP_OIM_SEND_ACTION ); soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD, - ic->acc->user, display_name_b64, oim->to, "bla", //md->passport_token, + ic->acc->user, display_name_b64, MSNP_VER, MSNP_BUILD, + oim->to, md->tokens[2], MSNP11_PROD_ID, md->lock_key ? md->lock_key : "", oim->number, oim->number, oim->msg ); diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 9eb1caef..f3231e91 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -110,6 +110,15 @@ "" \ "" \ "" \ + "" \ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ + "" \ + "" \ + "messengersecure.live.com" \ + "" \ + "" \ + "" \ + "" \ "" \ "" \ "" @@ -118,13 +127,13 @@ int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, #define SOAP_OIM_SEND_URL "https://ows.messenger.msn.com/OimWS/oim.asmx" -#define SOAP_OIM_SEND_ACTION "http://messenger.msn.com/ws/2004/09/oim/Store" +#define SOAP_OIM_SEND_ACTION "http://messenger.live.com/ws/2006/09/oim/Store2" #define SOAP_OIM_SEND_PAYLOAD \ "" \ "" \ "" \ - "" \ + "" \ "" \ "" \ "" \ -- cgit v1.2.3 From 4e4af1b0fe073fd2d43f4ea0d55f8deadbeb974d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 09:48:46 +0100 Subject: Remove some old Passport stuff, this is all in soap.[ch] now. --- protocols/msn/Makefile | 2 +- protocols/msn/msn.c | 2 +- protocols/msn/msn.h | 3 - protocols/msn/ns.c | 2 +- protocols/msn/passport.c | 172 ----------------------------------------------- protocols/msn/passport.h | 113 ------------------------------- protocols/msn/sb.c | 3 +- protocols/msn/soap.c | 60 ++++++++++------- protocols/msn/tables.c | 2 +- 9 files changed, 39 insertions(+), 320 deletions(-) delete mode 100644 protocols/msn/passport.c delete mode 100644 protocols/msn/passport.h (limited to 'protocols') diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index 28fe81c9..a14225d1 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -12,7 +12,7 @@ SRCDIR := $(SRCDIR)protocols/msn/ endif # [SH] Program variables -objects = msn.o msn_util.o ns.o passport.o sb.o soap.o tables.o +objects = msn.o msn_util.o ns.o sb.o soap.o tables.o LFLAGS += -r diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index ef70fe0c..7b881c67 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Main file; functions to be called from BitlBee */ diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 8abe6875..5c7949c9 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -232,7 +232,4 @@ int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ); void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ); void msn_sb_stop_keepalives( struct msn_switchboard *sb ); -/* invitation.c */ -void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); - #endif //_MSN_H diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 4ae8693d..40f96b21 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Notification server callbacks */ diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c deleted file mode 100644 index 7c896db1..00000000 --- a/protocols/msn/passport.c +++ /dev/null @@ -1,172 +0,0 @@ -/** passport.c - * - * Functions to login to Microsoft Passport service for Messenger - * Copyright (C) 2004-2008 Wilmer van der Gaast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that is will be useful, - * bit WITHOU ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "http_client.h" -#include "passport.h" -#include "msn.h" -#include "bitlbee.h" -#include "url.h" -#include "misc.h" -#include "xmltree.h" -#include -#include - -static int passport_get_token_real( struct msn_auth_data *mad ); -static void passport_get_token_ready( struct http_request *req ); - -int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie ) -{ - struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 ); - int i; - - mad->username = g_strdup( username ); - mad->password = g_strdup( password ); - mad->cookie = g_strdup( cookie ); - - mad->callback = func; - mad->data = data; - - mad->url = g_strdup( SOAP_AUTHENTICATION_URL ); - mad->ttl = 3; /* Max. # of redirects. */ - - /* HTTP-escape stuff and s/,/&/ */ - http_decode( mad->cookie ); - for( i = 0; mad->cookie[i]; i ++ ) - if( mad->cookie[i] == ',' ) - mad->cookie[i] = '&'; - - /* Microsoft doesn't allow password longer than 16 chars and silently - fails authentication if you give the "full version" of your passwd. */ - if( strlen( mad->password ) > MAX_PASSPORT_PWLEN ) - mad->password[MAX_PASSPORT_PWLEN] = 0; - - return passport_get_token_real( mad ); -} - -static int passport_get_token_real( struct msn_auth_data *mad ) -{ - char *post_payload, *post_request; - struct http_request *req; - url_t url; - - url_set( &url, mad->url ); - - post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD, - mad->username, - mad->password, - mad->cookie ); - - post_request = g_strdup_printf( SOAP_AUTHENTICATION_REQUEST, - url.file, url.host, - (int) strlen( post_payload ), - post_payload ); - - req = http_dorequest( url.host, url.port, 1, post_request, - passport_get_token_ready, mad ); - - g_free( post_request ); - g_free( post_payload ); - - return req != NULL; -} - -static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ); -static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data ); - -static const struct xt_handler_entry passport_xt_handlers[] = { - { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", passport_xt_extract_token }, - { "S:Fault", "S:Envelope", passport_xt_handle_fault }, - { NULL, NULL, NULL } -}; - -static void passport_get_token_ready( struct http_request *req ) -{ - struct msn_auth_data *mad = req->data; - struct xt_parser *parser; - - g_free( mad->url ); - g_free( mad->error ); - mad->url = mad->error = NULL; - - if( req->status_code == 200 ) - { - parser = xt_new( passport_xt_handlers, mad ); - xt_feed( parser, req->reply_body, req->body_size ); - xt_handle( parser, NULL, -1 ); - xt_free( parser ); - } - else - { - mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code, - req->status_string ? req->status_string : "unknown" ); - } - - if( mad->error == NULL && mad->token == NULL ) - mad->error = g_strdup( "Could not parse Passport server response" ); - - if( mad->url && mad->token == NULL ) - { - passport_get_token_real( mad ); - } - else - { - mad->callback( mad ); - - g_free( mad->url ); - g_free( mad->username ); - g_free( mad->password ); - g_free( mad->cookie ); - g_free( mad->token ); - g_free( mad->error ); - g_free( mad ); - } -} - -static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ) -{ - struct msn_auth_data *mad = data; - char *s; - - if( ( s = xt_find_attr( node, "Id" ) ) && - ( strncmp( s, "Compact", 7 ) == 0 || - strncmp( s, "PPToken", 7 ) == 0 ) ) - mad->token = g_memdup( node->text, node->text_len + 1 ); - - return XT_HANDLED; -} - -static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data ) -{ - struct msn_auth_data *mad = data; - struct xt_node *code = xt_find_node( node->children, "faultcode" ); - struct xt_node *string = xt_find_node( node->children, "faultstring" ); - struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" ); - - if( redirect && redirect->text_len && mad->ttl-- > 0 ) - mad->url = g_memdup( redirect->text, redirect->text_len + 1 ); - - if( code == NULL || code->text_len == 0 ) - mad->error = g_strdup( "Unknown error" ); - else - mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ? - string->text : "no description available" ); - - return XT_HANDLED; -} diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h deleted file mode 100644 index 517d2e91..00000000 --- a/protocols/msn/passport.h +++ /dev/null @@ -1,113 +0,0 @@ -/* passport.h - * - * Functions to login to Microsoft Passport service for Messenger - * Copyright (C) 2004-2008 Wilmer van der Gaast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that is will be useful, - * bit WITHOU ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Thanks to http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener - for the specs! */ - -#ifndef __PASSPORT_H__ -#define __PASSPORT_H__ - -#include -#include -#include -#include -#ifndef _WIN32 -#include -#include -#include -#include -#endif -#include "nogaim.h" - -#define MAX_PASSPORT_PWLEN 16 - -struct msn_auth_data -{ - char *url; - int ttl; - - char *username; - char *password; - char *cookie; - - /* The end result, the only thing we'll really be interested in - once finished. */ - char *token; - char *error; /* Yeah, or that... */ - - void (*callback)( struct msn_auth_data *mad ); - gpointer data; -}; - -#define SOAP_AUTHENTICATION_URL "https://loginnet.passport.com/RST.srf" - -#define SOAP_AUTHENTICATION_REQUEST \ -"POST %s HTTP/1.0\r\n" \ -"Accept: text/*\r\n" \ -"User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ -"Host: %s\r\n" \ -"Content-Length: %d\r\n" \ -"Cache-Control: no-cache\r\n" \ -"\r\n" \ -"%s" - -#define SOAP_AUTHENTICATION_PAYLOAD \ -"" \ -"" \ - "
" \ - "" \ - "{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}" \ - "4" \ - "1" \ - "" \ - "AQAAAAIAAABsYwQAAAAzMDg0" \ - "" \ - "" \ - "" \ - "%s" \ - "%s" \ - "" \ - "" \ - "
" \ - "" \ - "" \ - "" \ - "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ - "" \ - "" \ - "http://Passport.NET/tb" \ - "" \ - "" \ - "" \ - "" \ - "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ - "" \ - "" \ - "messenger.msn.com" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ -"
" - -int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie ); - -#endif /* __PASSPORT_H__ */ diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index b718d4e8..fdad2882 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2005 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Switchboard server callbacks and utilities */ @@ -26,7 +26,6 @@ #include #include "nogaim.h" #include "msn.h" -#include "passport.h" #include "md5.h" #include "soap.h" #include "invitation.h" diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 0fb36bb4..621e213b 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -1,25 +1,30 @@ -/** soap.c - * - * SOAP-related functions. Some manager at Microsoft apparently thought - * MSNP wasn't XMLy enough so someone stepped up and changed that. This - * is the result. - * - * Copyright (C) 2010 Wilmer van der Gaast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that is will be useful, - * bit WITHOU ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2010 Wilmer van der Gaast and others * + \********************************************************************/ + +/* MSN module - All the SOAPy XML stuff. + Some manager at Microsoft apparently thought MSNP wasn't XMLy enough so + someone stepped up and changed that. This is the result. Kilobytes and + more kilobytes of XML vomit to transfer tiny bits of informaiton. */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ #include "http_client.h" #include "soap.h" @@ -33,6 +38,11 @@ #include #include +/* This file tries to make SOAP stuff pretty simple to do by letting you just + provide a function to build a request, a few functions to parse various + parts of the response, and a function to run when the full response was + received and parsed. See the various examples below. */ + typedef enum { MSN_SOAP_OK, @@ -40,10 +50,6 @@ typedef enum MSN_SOAP_ABORT, } msn_soap_result_t; -struct msn_soap_req_data; - -typedef int (*msn_soap_func) ( struct msn_soap_req_data * ); - struct msn_soap_req_data { void *data; @@ -57,6 +63,8 @@ struct msn_soap_req_data msn_soap_func build_request, handle_response, free_data; }; +typedef int (*msn_soap_func) ( struct msn_soap_req_data * ); + static int msn_soap_send_request( struct msn_soap_req_data *req ); static int msn_soap_start( struct im_connection *ic, diff --git a/protocols/msn/tables.c b/protocols/msn/tables.c index 42b12aa9..fd7eca41 100644 --- a/protocols/msn/tables.c +++ b/protocols/msn/tables.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Some tables with useful data */ -- cgit v1.2.3 From 73efe3a6ea04ca19f3a4088990eda60ad852a94f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 12:07:45 +0100 Subject: Allow Passport authentication with @msn.com accounts. --- protocols/msn/soap.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 621e213b..c23d190a 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -160,7 +160,11 @@ static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_r struct msn_soap_passport_sso_data *sd = soap_req->data; struct im_connection *ic = soap_req->ic; - soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL ); + if( g_str_has_suffix( ic->acc->user, "@msn.com" ) ) + soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL_MSN ); + else + soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL ); + soap_req->payload = g_markup_printf_escaped( SOAP_PASSPORT_SSO_PAYLOAD, ic->acc->user, ic->acc->pass, sd->policy ); -- cgit v1.2.3 From 12767e39dbafc36d54995727ff2c6043e8292f16 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 12:30:40 +0100 Subject: Status/Away messages. --- protocols/msn/msn.c | 12 +++++++++++- protocols/msn/soap.c | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 7b881c67..99db509c 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -38,6 +38,8 @@ static void msn_init( account_t *acc ) set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc ); set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc ); + + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE; } static void msn_login( account_t *acc ) @@ -181,6 +183,7 @@ static GList *msn_away_states( struct im_connection *ic ) static void msn_set_away( struct im_connection *ic, char *state, char *message ) { char buf[1024]; + char *uux; struct msn_data *md = ic->proto_data; if( state == NULL ) @@ -189,7 +192,14 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) md->away_state = msn_away_state_list + 1; g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, md->away_state->code ); - msn_write( ic, buf, strlen( buf ) ); + if( !msn_write( ic, buf, strlen( buf ) ) ) + return; + + uux = g_markup_printf_escaped( "%s" + "", message ? message : "" ); + g_snprintf( buf, sizeof( buf ), "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); + if( !msn_write( ic, buf, strlen( buf ) ) ) + return; } static void msn_set_my_name( struct im_connection *ic, char *info ) diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index c23d190a..5eae3089 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -50,6 +50,9 @@ typedef enum MSN_SOAP_ABORT, } msn_soap_result_t; +struct msn_soap_req_data; +typedef int (*msn_soap_func) ( struct msn_soap_req_data * ); + struct msn_soap_req_data { void *data; @@ -63,8 +66,6 @@ struct msn_soap_req_data msn_soap_func build_request, handle_response, free_data; }; -typedef int (*msn_soap_func) ( struct msn_soap_req_data * ); - static int msn_soap_send_request( struct msn_soap_req_data *req ); static int msn_soap_start( struct im_connection *ic, @@ -526,7 +527,6 @@ static xt_status msn_soap_addressbook_group( struct xt_node *node, gpointer data struct xt_node *p; char *id = NULL, *name = NULL; struct msn_soap_req_data *soap_req = data; - struct im_connection *ic = soap_req->ic; if( ( p = node->parent ) && ( p = xt_find_node( p->children, "groupId" ) ) ) -- cgit v1.2.3 From d93c0eb9f3f5d2d2cd78f02422d0c0ed25743e3a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 13:20:59 +0100 Subject: Read incoming MSN status/away messages. --- protocols/bee.h | 1 + protocols/bee_user.c | 29 ++++++++++++++++++++++++++++- protocols/msn/ns.c | 20 ++++++++++++++++++++ protocols/msn/soap.h | 48 +++++++++++++++++++++++++++--------------------- 4 files changed, 76 insertions(+), 22 deletions(-) (limited to 'protocols') diff --git a/protocols/bee.h b/protocols/bee.h index 5792e988..6e3cf563 100644 --- a/protocols/bee.h +++ b/protocols/bee.h @@ -147,6 +147,7 @@ void bee_group_free( bee_t *bee ); * OPT_LOGGED_IN and OPT_AWAY. * - 'state' and 'message' can be NULL */ G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); +G_MODULE_EXPORT void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message ); G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */ G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, guint32 flags, time_t sent_at ); diff --git a/protocols/bee_user.c b/protocols/bee_user.c index 5acd5b83..86f87f86 100644 --- a/protocols/bee_user.c +++ b/protocols/bee_user.c @@ -186,8 +186,13 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, /* TODO(wilmer): OPT_AWAY, or just state == NULL ? */ bu->flags = flags; - bu->status = g_strdup( ( flags & OPT_AWAY ) && state == NULL ? "Away" : state ); bu->status_msg = g_strdup( message ); + if( state && *state ) + bu->status = g_strdup( state ); + else if( flags & OPT_AWAY ) + bu->status = g_strdup( "Away" ); + else + bu->status = NULL; if( bee->ui->user_status ) bee->ui->user_status( bee, bu, old ); @@ -197,6 +202,28 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, g_free( old ); } +/* Same, but only change the away/status message, not any away/online state info. */ +void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message ) +{ + bee_t *bee = ic->bee; + bee_user_t *bu, *old; + + if( !( bu = bee_user_by_handle( bee, ic, handle ) ) ) + { + return; + } + + old = g_memdup( bu, sizeof( bee_user_t ) ); + + bu->status_msg = g_strdup( message ); + + if( bee->ui->user_status ) + bee->ui->user_status( bee, bu, old ); + + g_free( old->status_msg ); + g_free( old ); +} + void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ) { bee_t *bee = ic->bee; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 40f96b21..0c067b8c 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -576,6 +576,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts >= 4 ) md->handler->msglen = atoi( cmd[3] ); } + else if( strcmp( cmd[0], "NOT" ) == 0 ) + { + /* Some kind of notification, not sure if it still exists + but we have to skip the payload or stuff breaks. */ + if( num_parts >= 3 ) + md->handler->msglen = atoi( cmd[2] ); + } else if( isdigit( cmd[0][0] ) ) { int num = atoi( cmd[0] ); @@ -685,6 +692,19 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int g_free( ct ); } } + else if( strcmp( cmd[0], "UBX" ) == 0 ) + { + struct xt_node *psm; + char *psm_text = NULL; + + psm = xt_from_string( msg ); + if( psm && strcmp( psm->name, "Data" ) == 0 && + ( psm = xt_find_node( psm->children, "PSM" ) ) ) + psm_text = psm->text; + + imcb_buddy_status_msg( ic, cmd[1], psm_text ); + xt_free_node( psm ); + } return( 1 ); } diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index f3231e91..14b0624b 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -1,24 +1,30 @@ -/* soap.h - * - * SOAP-related functions. Some manager at Microsoft apparently thought - * MSNP wasn't XMLy enough so someone stepped up and changed that. This - * is the result. - * - * Copyright (C) 2010 Wilmer van der Gaast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that is will be useful, - * bit WITHOU ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2010 Wilmer van der Gaast and others * + \********************************************************************/ + +/* MSN module - All the SOAPy XML stuff. + Some manager at Microsoft apparently thought MSNP wasn't XMLy enough so + someone stepped up and changed that. This is the result. Kilobytes and + more kilobytes of XML vomit to transfer tiny bits of informaiton. */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ /* Thanks to http://msnpiki.msnfanatic.com/ for lots of info on this! */ -- cgit v1.2.3 From 4452e69ab1f01793a37205db8227a2de2f211d3e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 14:06:11 +0100 Subject: Allow changing the display_name, now permanently! --- protocols/msn/msn.c | 37 ++++++++++++---------- protocols/msn/msn.h | 1 - protocols/msn/msn_util.c | 49 ++++------------------------- protocols/msn/ns.c | 80 ------------------------------------------------ protocols/msn/soap.c | 34 ++++++++++++++++++++ protocols/msn/soap.h | 33 ++++++++++++++++++++ protocols/nogaim.h | 2 ++ 7 files changed, 96 insertions(+), 140 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 99db509c..ed0881d1 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -24,6 +24,7 @@ */ #include "nogaim.h" +#include "soap.h" #include "msn.h" int msn_chat_id; @@ -34,8 +35,11 @@ static char *set_eval_display_name( set_t *set, char *value ); static void msn_init( account_t *acc ) { - set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); - set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc ); + set_t *s; + + s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; + set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc ); @@ -202,11 +206,6 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) return; } -static void msn_set_my_name( struct im_connection *ic, char *info ) -{ - msn_set_display_name( ic, info ); -} - static void msn_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ @@ -331,10 +330,9 @@ static char *set_eval_display_name( set_t *set, char *value ) { account_t *acc = set->data; struct im_connection *ic = acc->ic; - - /* Allow any name if we're offline. */ - if( ic == NULL ) - return value; + struct msn_data *md = ic->proto_data; + char buf[512]; + char *fn; if( strlen( value ) > 129 ) { @@ -342,10 +340,18 @@ static char *set_eval_display_name( set_t *set, char *value ) return NULL; } - /* Returning NULL would be better, because the server still has to - confirm the name change. However, it looks a bit confusing to the - user. */ - return msn_set_display_name( ic, value ) ? value : NULL; + msn_soap_addressbook_set_display_name( ic, value ); + + fn = g_malloc( strlen( value ) * 3 + 1 ); + strcpy( fn, value ); + http_encode( fn ); + g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", + ++md->trId, fn ); + g_free( fn ); + + /* Note: We don't actually know if the server accepted the new name, + and won't give proper feedback yet if it doesn't. */ + return msn_write( ic, buf, strlen( buf ) ) ? value : NULL; } static void msn_buddy_data_add( bee_user_t *bu ) @@ -374,7 +380,6 @@ void msn_initmodule() ret->away_states = msn_away_states; ret->set_away = msn_set_away; ret->get_info = msn_get_info; - ret->set_my_name = msn_set_my_name; ret->add_buddy = msn_add_buddy; ret->remove_buddy = msn_remove_buddy; ret->chat_msg = msn_chat_msg; diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 5c7949c9..1828cc8a 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -206,7 +206,6 @@ void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ); char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); -char *msn_http_encode( const char *input ); void msn_msgq_purge( struct im_connection *ic, GSList **list ); gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ); char *msn_p11_challenge( char *challenge ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 3a19d92f..bd1bea42 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -60,7 +60,7 @@ int msn_logged_in( struct im_connection *ic ) int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ) { struct msn_data *md = ic->proto_data; - char buf[1024], *realname, groupid[8]; + char buf[1024], realname[strlen(realname_)*3+1], groupid[8]; *groupid = '\0'; if( group ) @@ -93,9 +93,10 @@ int msn_buddy_list_add( struct im_connection *ic, const char *list, const char * if( l == NULL ) { - char *groupname = msn_http_encode( group ); + char groupname[strlen(group)+1]; + strcpy( groupname, group ); + http_encode( groupname ); g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 ); - g_free( groupname ); return msn_write( ic, buf, strlen( buf ) ); } else @@ -108,9 +109,9 @@ int msn_buddy_list_add( struct im_connection *ic, const char *list, const char * } } - realname = msn_http_encode( realname_ ); + strcpy( realname, realname_ ); + http_encode( realname ); g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid ); - g_free( realname ); return msn_write( ic, buf, strlen( buf ) ); } @@ -379,32 +380,6 @@ int msn_handler( struct msn_handler_data *h ) return( 1 ); } -/* The difference between this function and the normal http_encode() function - is that this one escapes every 7-bit ASCII character because this is said - to avoid some lame server-side checks when setting a real-name. Also, - non-ASCII characters are not escaped because MSN servers don't seem to - appreciate that! */ -char *msn_http_encode( const char *input ) -{ - char *ret, *s; - int i; - - ret = s = g_new0( char, strlen( input ) * 3 + 1 ); - for( i = 0; input[i]; i ++ ) - if( input[i] & 128 ) - { - *s = input[i]; - s ++; - } - else - { - g_snprintf( s, 4, "%%%02X", input[i] ); - s += 3; - } - - return ret; -} - void msn_msgq_purge( struct im_connection *ic, GSList **list ) { struct msn_message *m; @@ -445,18 +420,6 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ) g_string_free( ret, TRUE ); } -gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ) -{ - char *fn = msn_http_encode( rawname ); - struct msn_data *md = ic->proto_data; - char buf[1024]; - - g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn ); - g_free( fn ); - - return msn_write( ic, buf, strlen( buf ) ) != 0; -} - /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ char *msn_p11_challenge( char *challenge ) { diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 0c067b8c..777a6ebd 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -34,7 +34,6 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); -static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); static void msn_ns_send_adl( struct im_connection *ic ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) @@ -473,40 +472,6 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imc_logout( ic, allow_reconnect ); return( 0 ); } -#if 0 - /* Discard this one completely for now since I don't care about the ack - and since MSN servers can apparently screw up the formatting. */ - else if( strcmp( cmd[0], "REA" ) == 0 ) - { - if( num_parts < 5 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - - if( g_strcasecmp( cmd[3], ic->acc->user ) == 0 ) - { - set_t *s; - - http_decode( cmd[4] ); - strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); - ic->displayname[sizeof(ic->displayname)-1] = 0; - - if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) - { - g_free( s->value ); - s->value = g_strdup( cmd[4] ); - } - } - else - { - /* This is not supposed to happen, but let's handle it anyway... */ - http_decode( cmd[4] ); - imcb_rename_buddy( ic, cmd[3], cmd[4] ); - } - } -#endif else if( strcmp( cmd[0], "IPG" ) == 0 ) { imcb_error( ic, "Received IPG command, we don't handle them yet." ); @@ -800,48 +765,3 @@ static void msn_ns_send_adl( struct im_connection *ic ) g_free( adls ); xt_free_node( adl ); } - -static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ) -{ - set_t *s; - - if( ( s = set_find( &ic->acc->set, "display_name" ) ) == NULL ) - return FALSE; /* Shouldn't happen.. */ - - http_decode( name ); - - if( s->value && strcmp( s->value, name ) == 0 ) - { - return TRUE; - /* The names match, nothing to worry about. */ - } - else if( s->value != NULL && - ( strcmp( name, ic->acc->user ) == 0 || - set_getbool( &ic->acc->set, "local_display_name" ) ) ) - { - /* The server thinks our display name is our e-mail address - which is probably wrong, or the user *wants* us to do this: - Always use the locally set display_name. */ - return msn_set_display_name( ic, s->value ); - } - else - { - if( s->value && *s->value ) - imcb_log( ic, "BitlBee thinks your display name is `%s' but " - "the MSN server says it's `%s'. Using the MSN " - "server's name. Set local_display_name to true " - "to use the local name.", s->value, name ); - - if( g_utf8_validate( name, -1, NULL ) ) - { - g_free( s->value ); - s->value = g_strdup( name ); - } - else - { - imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); - } - - return TRUE; - } -} diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 5eae3089..cd54858f 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -608,3 +608,37 @@ int msn_soap_addressbook_request( struct im_connection *ic ) msn_soap_addressbook_handle_response, msn_soap_addressbook_free_data ); } + +/* Variant: Change our display name. */ +static int msn_soap_ab_namechange_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + + soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); + soap_req->action = g_strdup( SOAP_AB_NAMECHANGE_ACTION ); + soap_req->payload = g_markup_printf_escaped( SOAP_AB_NAMECHANGE_PAYLOAD, + md->tokens[1], (char *) soap_req->data ); + + return 1; +} + +static int msn_soap_ab_namechange_handle_response( struct msn_soap_req_data *soap_req ) +{ + /* TODO: Ack the change? Not sure what the NAKs look like.. */ + return MSN_SOAP_OK; +} + +static int msn_soap_ab_namechange_free_data( struct msn_soap_req_data *soap_req ) +{ + g_free( soap_req->data ); + return 0; +} + +int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ) +{ + return msn_soap_start( ic, g_strdup( new ), + msn_soap_ab_namechange_build_request, + NULL, + msn_soap_ab_namechange_handle_response, + msn_soap_ab_namechange_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 14b0624b..5673583a 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -219,7 +219,40 @@ int msn_soap_memlist_request( struct im_connection *ic ); "
" \ "" +#define SOAP_AB_NAMECHANGE_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" + +#define SOAP_AB_NAMECHANGE_PAYLOAD \ +"" \ +"" \ + "" \ + "" \ + "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ + "false" \ + "Initial" \ + "" \ + "" \ + "false" \ + "%s" \ + "" \ + "" \ + "" \ + "" \ + "00000000-0000-0000-0000-000000000000" \ + "" \ + "" \ + "" \ + "Me" \ + "%s" \ + "" \ + "DisplayName" \ + "" \ + "" \ + "" \ + "" \ +"" + int msn_soap_addressbook_request( struct im_connection *ic ); +int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ); #endif /* __SOAP_H__ */ diff --git a/protocols/nogaim.h b/protocols/nogaim.h index be67bb24..90254508 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -193,6 +193,8 @@ struct prpl { /* Request profile info. Free-formatted stuff, the IM module gives back this info via imcb_log(). Implementing these are optional. */ void (* get_info) (struct im_connection *, char *who); + /* set_my_name is *DEPRECATED*, not used by the UI anymore. Use the + display_name setting instead. */ void (* set_my_name) (struct im_connection *, char *name); void (* set_name) (struct im_connection *, char *who, char *name); -- cgit v1.2.3 From 584867592546f43f857645e02169d135f0df25e8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 14:32:46 +0100 Subject: The contact's full name is in a different field now in NLN messages. --- protocols/msn/ns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 777a6ebd..a1b88ae1 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -347,8 +347,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } - http_decode( cmd[3] ); - imcb_rename_buddy( ic, cmd[2], cmd[3] ); + http_decode( cmd[4] ); + imcb_rename_buddy( ic, cmd[2], cmd[4] ); st = msn_away_state_by_code( cmd[1] ); if( !st ) -- cgit v1.2.3 From e5854a80111e337be01cf1e506073a231fac1c3d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 15:50:10 +0100 Subject: Show incoming auth. requests (although responding to them currently causes a disconnect). --- protocols/msn/msn.h | 2 +- protocols/msn/msn_util.c | 19 ++++++--- protocols/msn/ns.c | 109 ++++++++++++++++++++++++++++------------------- protocols/msn/soap.c | 8 ++++ 4 files changed, 85 insertions(+), 53 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 1828cc8a..d9609189 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -202,7 +202,7 @@ int msn_write( struct im_connection *ic, char *s, int len ); int msn_logged_in( struct im_connection *ic ); int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ); int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group ); -void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ); +void msn_buddy_ask( bee_user_t *bu ); char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index bd1bea42..6a5afd93 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -171,19 +171,24 @@ static void msn_buddy_ask_no( void *data ) g_free( bla ); } -void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ) +void msn_buddy_ask( bee_user_t *bu ) { - struct msn_buddy_ask_data *bla = g_new0( struct msn_buddy_ask_data, 1 ); + struct msn_buddy_ask_data *bla; + struct msn_buddy_data *bd = bu->data; char buf[1024]; - bla->ic = ic; - bla->handle = g_strdup( handle ); - bla->realname = g_strdup( realname ); + if( ( bd->flags & 30 ) != 8 && ( bd->flags & 30 ) != 16 ) + return; + + bla = g_new0( struct msn_buddy_ask_data, 1 ); + bla->ic = bu->ic; + bla->handle = g_strdup( bu->handle ); + bla->realname = g_strdup( bu->fullname ); g_snprintf( buf, sizeof( buf ), "The user %s (%s) wants to add you to his/her buddy list.", - handle, realname ); - imcb_ask( ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); + bu->handle, bu->fullname ); + imcb_ask( bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); } char *msn_findheader( char *text, char *header, int len ) diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index a1b88ae1..7518dc25 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -278,6 +278,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) msn_write( ic, buf, strlen( buf ) ); } + else if( num_parts >= 3 ) + { + md->handler->msglen = atoi( cmd[2] ); + } } else if( strcmp( cmd[0], "PRP" ) == 0 ) { @@ -411,46 +415,6 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) sb->who = g_strdup( cmd[5] ); } } - else if( strcmp( cmd[0], "ADD" ) == 0 ) - { - if( num_parts >= 6 && strcmp( cmd[2], "RL" ) == 0 ) - { - GSList *l; - - http_decode( cmd[5] ); - - if( strchr( cmd[4], '@' ) == NULL ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return 0; - } - - /* We got added by someone. If we don't have this - person in permit/deny yet, inform the user. */ - for( l = ic->permit; l; l = l->next ) - if( g_strcasecmp( l->data, cmd[4] ) == 0 ) - return 1; - - for( l = ic->deny; l; l = l->next ) - if( g_strcasecmp( l->data, cmd[4] ) == 0 ) - return 1; - - msn_buddy_ask( ic, cmd[4], cmd[5] ); - } - else if( num_parts >= 6 && strcmp( cmd[2], "FL" ) == 0 ) - { - const char *group = NULL; - int num; - - if( cmd[6] != NULL && sscanf( cmd[6], "%d", &num ) == 1 && num < md->groupcount ) - group = md->grouplist[num]; - - http_decode( cmd[5] ); - imcb_add_buddy( ic, cmd[4], group ); - imcb_rename_buddy( ic, cmd[4], cmd[5] ); - } - } else if( strcmp( cmd[0], "OUT" ) == 0 ) { int allow_reconnect = TRUE; @@ -485,6 +449,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } } +#if 0 else if( strcmp( cmd[0], "ADG" ) == 0 ) { char *group = g_strdup( cmd[3] ); @@ -529,6 +494,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } } } +#endif else if( strcmp( cmd[0], "GCF" ) == 0 ) { /* Coming up is cmd[2] bytes of stuff we're supposed to @@ -537,16 +503,16 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "UBX" ) == 0 ) { - /* Status message. Parser coming soon. */ + /* Status message. */ if( num_parts >= 4 ) md->handler->msglen = atoi( cmd[3] ); } else if( strcmp( cmd[0], "NOT" ) == 0 ) { - /* Some kind of notification, not sure if it still exists - but we have to skip the payload or stuff breaks. */ - if( num_parts >= 3 ) - md->handler->msglen = atoi( cmd[2] ); + /* Some kind of notification, poorly documented but + apparently used to announce address book changes. */ + if( num_parts >= 2 ) + md->handler->msglen = atoi( cmd[1] ); } else if( isdigit( cmd[0][0] ) ) { @@ -670,6 +636,56 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int imcb_buddy_status_msg( ic, cmd[1], psm_text ); xt_free_node( psm ); } + else if( strcmp( cmd[0], "ADL" ) == 0 ) + { + struct xt_node *adl, *d, *c; + + if( !( adl = xt_from_string( msg ) ) ) + return 1; + + for( d = adl->children; d; d = d->next ) + { + char *dn; + if( strcmp( d->name, "d" ) != 0 || + ( dn = xt_find_attr( d, "n" ) ) == NULL ) + continue; + for( c = d->children; c; c = c->next ) + { + bee_user_t *bu; + struct msn_buddy_data *bd; + char *cn, *handle, *f, *l; + int flags; + + if( strcmp( c->name, "c" ) != 0 || + ( l = xt_find_attr( c, "l" ) ) == NULL || + ( cn = xt_find_attr( c, "n" ) ) == NULL ) + continue; + + handle = g_strdup_printf( "%s@%s", cn, dn ); + if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || + ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) ) + { + g_free( handle ); + continue; + } + g_free( handle ); + bd = bu->data; + + if( ( f = xt_find_attr( c, "f" ) ) ) + { + http_decode( f ); + imcb_rename_buddy( ic, bu->handle, f ); + } + + flags = atoi( l ) & 15; + if( bd->flags != flags ) + { + bd->flags = flags; + msn_buddy_ask( bu ); + } + } + } + } return( 1 ); } @@ -717,6 +733,9 @@ static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) char *domain; char l[4]; + if( ( bd->flags & 7 ) == 0 ) + return FALSE; + strcpy( handle, bu->handle ); if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */ return FALSE; diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index cd54858f..8cc241b8 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -476,9 +476,17 @@ static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) else if( strcmp( role, "Block" ) == 0 ) bd->flags |= MSN_BUDDY_BL; else if( strcmp( role, "Reverse" ) == 0 ) + { bd->flags |= MSN_BUDDY_RL; + msn_buddy_ask( bu ); + } else if( strcmp( role, "Pending" ) == 0 ) + { bd->flags |= MSN_BUDDY_PL; + msn_buddy_ask( bu ); + } + + printf( "%s %d\n", handle, bd->flags ); return XT_HANDLED; } -- cgit v1.2.3 From 193dc742d357bb604fff8921417c74ddf9e8729c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 17:16:52 +0100 Subject: Responses to add requests work now. --- protocols/msn/msn.c | 14 ++++----- protocols/msn/msn.h | 4 +-- protocols/msn/msn_util.c | 74 ++++++++++++++++++++++++++++++++++++------- protocols/msn/ns.c | 7 +++-- protocols/msn/soap.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ protocols/msn/soap.h | 41 ++++++++++++++++++++++++ 6 files changed, 198 insertions(+), 23 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index ed0881d1..679ac65e 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -216,14 +216,14 @@ static void msn_add_buddy( struct im_connection *ic, char *who, char *group ) { struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who ); - msn_buddy_list_add( ic, "FL", who, who, group ); + msn_buddy_list_add( ic, MSN_BUDDY_FL, who, who, group ); if( bu && bu->group ) - msn_buddy_list_remove( ic, "FL", who, bu->group->name ); + msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, bu->group->name ); } static void msn_remove_buddy( struct im_connection *ic, char *who, char *group ) { - msn_buddy_list_remove( ic, "FL", who, NULL ); + msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, NULL ); } static void msn_chat_msg( struct groupchat *c, char *message, int flags ) @@ -288,19 +288,19 @@ static void msn_keepalive( struct im_connection *ic ) static void msn_add_permit( struct im_connection *ic, char *who ) { - msn_buddy_list_add( ic, "AL", who, who, NULL ); + msn_buddy_list_add( ic, MSN_BUDDY_AL, who, who, NULL ); } static void msn_rem_permit( struct im_connection *ic, char *who ) { - msn_buddy_list_remove( ic, "AL", who, NULL ); + msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL ); } static void msn_add_deny( struct im_connection *ic, char *who ) { struct msn_switchboard *sb; - msn_buddy_list_add( ic, "BL", who, who, NULL ); + msn_buddy_list_add( ic, MSN_BUDDY_BL, who, who, NULL ); /* If there's still a conversation with this person, close it. */ if( ( sb = msn_sb_by_handle( ic, who ) ) ) @@ -311,7 +311,7 @@ static void msn_add_deny( struct im_connection *ic, char *who ) static void msn_rem_deny( struct im_connection *ic, char *who ) { - msn_buddy_list_remove( ic, "BL", who, NULL ); + msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL ); } static int msn_send_typing( struct im_connection *ic, char *who, int typing ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index d9609189..862d1ef7 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -200,8 +200,8 @@ void msn_auth_got_contact_list( struct im_connection *ic ); /* msn_util.c */ int msn_write( struct im_connection *ic, char *s, int len ); int msn_logged_in( struct im_connection *ic ); -int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ); -int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group ); +int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group ); +int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ); void msn_buddy_ask( bee_user_t *bu ); char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 6a5afd93..54bfad7f 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -26,6 +26,7 @@ #include "nogaim.h" #include "msn.h" #include "md5.h" +#include "soap.h" #include int msn_write( struct im_connection *ic, char *s, int len ) @@ -57,12 +58,31 @@ int msn_logged_in( struct im_connection *ic ) return( 0 ); } -int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ) +static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list ) +{ + char *domain, handle[strlen(handle_)+1]; + + strcpy( handle, handle_ ); + if( ( domain = strchr( handle, '@' ) ) ) + *(domain + ++) = '\0'; + else + return NULL; + + return g_markup_printf_escaped( "", + domain, handle, list ); +} + +int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group ) { struct msn_data *md = ic->proto_data; - char buf[1024], realname[strlen(realname_)*3+1], groupid[8]; + char buf[1024], groupid[8]; + bee_user_t *bu; + struct msn_buddy_data *bd; + char *adl; *groupid = '\0'; +#if 0 if( group ) { int i; @@ -108,20 +128,36 @@ int msn_buddy_list_add( struct im_connection *ic, const char *list, const char * } } } +#endif + + if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) || + !( bd = bu->data ) || bd->flags & list ) + return 1; - strcpy( realname, realname_ ); - http_encode( realname ); - g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid ); + bd->flags |= list; - return msn_write( ic, buf, strlen( buf ) ); + msn_soap_memlist_edit( ic, who, TRUE, list ); + + if( ( adl = adlrml_entry( who, list ) ) ) + { + g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n%s", + ++md->trId, strlen( adl ), adl ); + g_free( adl ); + + return msn_write( ic, buf, strlen( buf ) ); + } } -int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group ) +int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ) { struct msn_data *md = ic->proto_data; char buf[1024], groupid[8]; + bee_user_t *bu; + struct msn_buddy_data *bd; + char *adl; *groupid = '\0'; +#if 0 if( group ) { int i; @@ -132,10 +168,24 @@ int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who break; } } +#endif + + if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) || + !( bd = bu->data ) || !( bd->flags & list ) ) + return 1; + + bd->flags &= ~list; - g_snprintf( buf, sizeof( buf ), "REM %d %s %s%s\r\n", ++md->trId, list, who, groupid ); - if( msn_write( ic, buf, strlen( buf ) ) ) - return( 1 ); + msn_soap_memlist_edit( ic, who, FALSE, list ); + + if( ( adl = adlrml_entry( who, list ) ) ) + { + g_snprintf( buf, sizeof( buf ), "RML %d %zd\r\n%s", + ++md->trId, strlen( adl ), adl ); + g_free( adl ); + + return msn_write( ic, buf, strlen( buf ) ); + } return( 0 ); } @@ -151,7 +201,7 @@ static void msn_buddy_ask_yes( void *data ) { struct msn_buddy_ask_data *bla = data; - msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname, NULL ); + msn_buddy_list_add( bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL ); imcb_ask_add( bla->ic, bla->handle, NULL ); @@ -164,7 +214,7 @@ static void msn_buddy_ask_no( void *data ) { struct msn_buddy_ask_data *bla = data; - msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname, NULL ); + msn_buddy_list_add( bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL ); g_free( bla->handle ); g_free( bla->realname ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 7518dc25..23b8f3b1 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -263,10 +263,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 ) { char buf[1024]; - char *fn_raw = set_getstr( &ic->acc->set, "display_name" ); + char *fn_raw; char *fn; - if( fn_raw == NULL ) + if( ic->flags & OPT_LOGGED_IN ) + return 1; + + if( ( fn_raw = set_getstr( &ic->acc->set, "display_name" ) ) == NULL ) fn_raw = ic->acc->user; fn = g_malloc( strlen( fn_raw ) * 3 + 1 ); strcpy( fn, fn_raw ); diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 8cc241b8..93bb37a6 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -516,6 +516,87 @@ int msn_soap_memlist_request( struct im_connection *ic ) msn_soap_memlist_free_data ); } +/* Variant: Adding/Removing people */ +struct msn_soap_memlist_edit_data +{ + char *handle; + gboolean add; + msn_buddy_flags_t list; +}; + +static int msn_soap_memlist_edit_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + struct msn_soap_memlist_edit_data *med = soap_req->data; + char *add, *scenario, *list; + + soap_req->url = g_strdup( SOAP_MEMLIST_URL ); + if( med->add ) + { + soap_req->action = g_strdup( SOAP_MEMLIST_ADD_ACTION ); + add = "Add"; + } + else + { + soap_req->action = g_strdup( SOAP_MEMLIST_DEL_ACTION ); + add = "Delete"; + } + switch( med->list ) + { + case MSN_BUDDY_AL: + scenario = "BlockUnblock"; + list = "Allow"; + break; + case MSN_BUDDY_BL: + scenario = "BlockUnblock"; + list = "Block"; + break; + case MSN_BUDDY_RL: + scenario = "Timer"; + list = "Reverse"; + break; + case MSN_BUDDY_PL: + default: + scenario = "Timer"; + list = "Pending"; + break; + } + soap_req->payload = g_markup_printf_escaped( SOAP_MEMLIST_EDIT_PAYLOAD, + scenario, md->tokens[1], add, list, med->handle, add ); + + return 1; +} + +static int msn_soap_memlist_edit_handle_response( struct msn_soap_req_data *soap_req ) +{ + return MSN_SOAP_OK; +} + +static int msn_soap_memlist_edit_free_data( struct msn_soap_req_data *soap_req ) +{ + struct msn_soap_memlist_edit_data *med = soap_req->data; + + g_free( med->handle ); + g_free( med ); + + return 0; +} + +int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolean add, int list ) +{ + struct msn_soap_memlist_edit_data *med; + + med = g_new0( struct msn_soap_memlist_edit_data, 1 ); + med->handle = g_strdup( handle ); + med->add = add; + med->list = list; + + return msn_soap_start( ic, med, msn_soap_memlist_edit_build_request, + NULL, + msn_soap_memlist_edit_handle_response, + msn_soap_memlist_edit_free_data ); +} + /* addressbook: Fetching the membership list (NOT address book) */ diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 5673583a..9ef68df9 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -189,7 +189,48 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); "
" \ "" +#define SOAP_MEMLIST_ADD_ACTION "http://www.msn.com/webservices/AddressBook/AddMember" +#define SOAP_MEMLIST_DEL_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember" + +#define SOAP_MEMLIST_EDIT_PAYLOAD \ +"" \ +"" \ + "" \ + "" \ + "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ + "false" \ + "%s" \ + "" \ + "" \ + "false" \ + "%s" \ + "" \ + "" \ + "" \ + "<%sMember xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "" \ + "0" \ + "Messenger" \ + "" \ + "" \ + "" \ + "" \ + "%s" \ + "" \ + "" \ + "Passport" \ + "Accepted" \ + "%s" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ +"" + int msn_soap_memlist_request( struct im_connection *ic ); +int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolean add, int list ); #define SOAP_ADDRESSBOOK_URL "http://contacts.msn.com/abservice/abservice.asmx" -- cgit v1.2.3 From 6ddb2236943384d45cacd08e02cb4ef9ed03bba3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 20:57:13 +0100 Subject: Separate boilerplate and body of abservice SOAP requests since the former's the same all the time (and I have to add some more request types). --- protocols/msn/msn_util.c | 4 ++- protocols/msn/soap.c | 28 +++++++++++++++---- protocols/msn/soap.h | 71 +++++++++--------------------------------------- 3 files changed, 39 insertions(+), 64 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 54bfad7f..b7fdda28 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -146,6 +146,8 @@ int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const return msn_write( ic, buf, strlen( buf ) ); } + + return 1; } int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ) @@ -187,7 +189,7 @@ int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, con return msn_write( ic, buf, strlen( buf ) ); } - return( 0 ); + return 1; } struct msn_buddy_ask_data diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 93bb37a6..130df840 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -146,6 +146,24 @@ static void msn_soap_handle_response( struct http_request *http_req ) } } +static char *msn_soap_abservice_build( const char *body_fmt, const char *scenario, const char *ticket, ... ) +{ + va_list params; + char *ret, *format, *body; + + format = g_markup_printf_escaped( SOAP_ABSERVICE_PAYLOAD, scenario, ticket ); + + va_start( params, ticket ); + body = g_strdup_vprintf( body_fmt, params ); + va_end( params ); + + ret = g_strdup_printf( format, body ); + g_free( body ); + g_free( format ); + + return ret; +} + /* passport_sso: Authentication MSNP15+ */ @@ -444,7 +462,7 @@ static int msn_soap_memlist_build_request( struct msn_soap_req_data *soap_req ) soap_req->url = g_strdup( SOAP_MEMLIST_URL ); soap_req->action = g_strdup( SOAP_MEMLIST_ACTION ); - soap_req->payload = g_markup_printf_escaped( SOAP_MEMLIST_PAYLOAD, md->tokens[1] ); + soap_req->payload = msn_soap_abservice_build( SOAP_MEMLIST_PAYLOAD, "Initial", md->tokens[1] ); return 1; } @@ -561,7 +579,7 @@ static int msn_soap_memlist_edit_build_request( struct msn_soap_req_data *soap_r list = "Pending"; break; } - soap_req->payload = g_markup_printf_escaped( SOAP_MEMLIST_EDIT_PAYLOAD, + soap_req->payload = msn_soap_abservice_build( SOAP_MEMLIST_EDIT_PAYLOAD, scenario, md->tokens[1], add, list, med->handle, add ); return 1; @@ -606,7 +624,7 @@ static int msn_soap_addressbook_build_request( struct msn_soap_req_data *soap_re soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); soap_req->action = g_strdup( SOAP_ADDRESSBOOK_ACTION ); - soap_req->payload = g_markup_printf_escaped( SOAP_ADDRESSBOOK_PAYLOAD, md->tokens[1] ); + soap_req->payload = msn_soap_abservice_build( SOAP_ADDRESSBOOK_PAYLOAD, "Initial", md->tokens[1] ); return 1; } @@ -705,8 +723,8 @@ static int msn_soap_ab_namechange_build_request( struct msn_soap_req_data *soap_ soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); soap_req->action = g_strdup( SOAP_AB_NAMECHANGE_ACTION ); - soap_req->payload = g_markup_printf_escaped( SOAP_AB_NAMECHANGE_PAYLOAD, - md->tokens[1], (char *) soap_req->data ); + soap_req->payload = msn_soap_abservice_build( SOAP_AB_NAMECHANGE_PAYLOAD, + "Initial", md->tokens[1], (char *) soap_req->data ); return 1; } diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 9ef68df9..8ce893df 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -166,17 +166,14 @@ int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); -#define SOAP_MEMLIST_URL "http://contacts.msn.com/abservice/SharingService.asmx" -#define SOAP_MEMLIST_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership" - -#define SOAP_MEMLIST_PAYLOAD \ +#define SOAP_ABSERVICE_PAYLOAD \ "" \ "" \ "" \ "" \ "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ "false" \ - "Initial" \ + "%s" \ "" \ "" \ "false" \ @@ -184,29 +181,21 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); "" \ "" \ "" \ - "MessengerInvitationSocialNetworkSpaceProfile" \ - "" \ + "%%s" \ "" \ "" +#define SOAP_MEMLIST_URL "http://contacts.msn.com/abservice/SharingService.asmx" +#define SOAP_MEMLIST_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership" + +#define SOAP_MEMLIST_PAYLOAD \ + "MessengerInvitationSocialNetworkSpaceProfile" \ + "" + #define SOAP_MEMLIST_ADD_ACTION "http://www.msn.com/webservices/AddressBook/AddMember" #define SOAP_MEMLIST_DEL_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember" #define SOAP_MEMLIST_EDIT_PAYLOAD \ -"" \ -"" \ - "" \ - "" \ - "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ - "false" \ - "%s" \ - "" \ - "" \ - "false" \ - "%s" \ - "" \ - "" \ - "" \ "<%sMember xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ "" \ "0" \ @@ -225,9 +214,7 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq ); "" \ "" \ "" \ - "" \ - "" \ -"" + "" int msn_soap_memlist_request( struct im_connection *ic ); int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolean add, int list ); @@ -237,46 +224,16 @@ int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolea #define SOAP_ADDRESSBOOK_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll" #define SOAP_ADDRESSBOOK_PAYLOAD \ -"" \ -"" \ - "" \ - "" \ - "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ - "false" \ - "Initial" \ - "" \ - "" \ - "false" \ - "%s" \ - "" \ - "" \ - "" \ "" \ "00000000-0000-0000-0000-000000000000" \ "Full" \ "false" \ "0001-01-01T00:00:00.0000000-08:00" \ - "" \ - "" \ -"" + "" #define SOAP_AB_NAMECHANGE_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" #define SOAP_AB_NAMECHANGE_PAYLOAD \ -"" \ -"" \ - "" \ - "" \ - "CFE80F9D-180F-4399-82AB-413F33A1FA11" \ - "false" \ - "Initial" \ - "" \ - "" \ - "false" \ - "%s" \ - "" \ - "" \ - "" \ "" \ "00000000-0000-0000-0000-000000000000" \ "" \ @@ -288,9 +245,7 @@ int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolea "DisplayName" \ "" \ "" \ - "" \ - "" \ -"" + "" int msn_soap_addressbook_request( struct im_connection *ic ); int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ); -- cgit v1.2.3 From 4fc95c57361193c5338d9916fd37cc8a939067cd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 22:33:33 +0100 Subject: Add/Remove support. --- protocols/msn/msn_util.c | 15 ++++++--- protocols/msn/soap.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ protocols/msn/soap.h | 37 ++++++++++++++++++++- protocols/msn/tables.c | 2 ++ 4 files changed, 135 insertions(+), 5 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index b7fdda28..84d68b8c 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -73,7 +73,7 @@ static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list ) domain, handle, list ); } -int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group ) +int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group ) { struct msn_data *md = ic->proto_data; char buf[1024], groupid[8]; @@ -130,13 +130,17 @@ int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const } #endif - if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) || + if( !( ( bu = bee_user_by_handle( ic->bee, ic, who ) ) || + ( bu = bee_user_new( ic->bee, ic, who, 0 ) ) ) || !( bd = bu->data ) || bd->flags & list ) return 1; bd->flags |= list; - msn_soap_memlist_edit( ic, who, TRUE, list ); + if( list == MSN_BUDDY_FL ) + msn_soap_ab_contact_add( ic, bu ); + else + msn_soap_memlist_edit( ic, who, TRUE, list ); if( ( adl = adlrml_entry( who, list ) ) ) { @@ -178,7 +182,10 @@ int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, con bd->flags &= ~list; - msn_soap_memlist_edit( ic, who, FALSE, list ); + if( list == MSN_BUDDY_FL ) + msn_soap_ab_contact_del( ic, bu ); + else + msn_soap_memlist_edit( ic, who, FALSE, list ); if( ( adl = adlrml_entry( who, list ) ) ) { diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 130df840..13ef7e37 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -749,3 +749,89 @@ int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char msn_soap_ab_namechange_handle_response, msn_soap_ab_namechange_free_data ); } + +/* Add a contact. */ +static int msn_soap_ab_contact_add_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + bee_user_t *bu = soap_req->data; + + soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); + soap_req->action = g_strdup( SOAP_AB_CONTACT_ADD_ACTION ); + soap_req->payload = msn_soap_abservice_build( SOAP_AB_CONTACT_ADD_PAYLOAD, + "ContactSave", md->tokens[1], bu->handle, bu->fullname ? bu->fullname : bu->handle ); + + return 1; +} + +static xt_status msn_soap_ab_contact_add_cid( struct xt_node *node, gpointer data ) +{ + struct msn_soap_req_data *soap_req = data; + bee_user_t *bu = soap_req->data; + struct msn_buddy_data *bd = bu->data; + + g_free( bd->cid ); + bd->cid = g_strdup( node->text ); + + return XT_HANDLED; +} + +static const struct xt_handler_entry msn_soap_ab_contact_add_parser[] = { + { "guid", "ABContactAddResult", msn_soap_ab_contact_add_cid }, + { NULL, NULL, NULL } +}; + +static int msn_soap_ab_contact_add_handle_response( struct msn_soap_req_data *soap_req ) +{ + /* TODO: Ack the change? Not sure what the NAKs look like.. */ + return MSN_SOAP_OK; +} + +static int msn_soap_ab_contact_add_free_data( struct msn_soap_req_data *soap_req ) +{ + return 0; +} + +int msn_soap_ab_contact_add( struct im_connection *ic, bee_user_t *bu ) +{ + return msn_soap_start( ic, bu, + msn_soap_ab_contact_add_build_request, + msn_soap_ab_contact_add_parser, + msn_soap_ab_contact_add_handle_response, + msn_soap_ab_contact_add_free_data ); +} + +/* Remove a contact. */ +static int msn_soap_ab_contact_del_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + bee_user_t *bu = soap_req->data; + struct msn_buddy_data *bd = bu->data; + + soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); + soap_req->action = g_strdup( SOAP_AB_CONTACT_DEL_ACTION ); + soap_req->payload = msn_soap_abservice_build( SOAP_AB_CONTACT_DEL_PAYLOAD, + "Timer", md->tokens[1], bd->cid ); + + return 1; +} + +static int msn_soap_ab_contact_del_handle_response( struct msn_soap_req_data *soap_req ) +{ + /* TODO: Ack the change? Not sure what the NAKs look like.. */ + return MSN_SOAP_OK; +} + +static int msn_soap_ab_contact_del_free_data( struct msn_soap_req_data *soap_req ) +{ + return 0; +} + +int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ) +{ + return msn_soap_start( ic, bu, + msn_soap_ab_contact_del_build_request, + NULL, + msn_soap_ab_contact_del_handle_response, + msn_soap_ab_contact_del_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 8ce893df..19a5c6ae 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -247,8 +247,43 @@ int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolea "" \ "" +#define SOAP_AB_CONTACT_ADD_ACTION "http://www.msn.com/webservices/AddressBook/ABContactAdd" + +#define SOAP_AB_CONTACT_ADD_PAYLOAD \ + "" \ + "00000000-0000-0000-0000-000000000000" \ + "" \ + "" \ + "" \ + "LivePending" \ + "%s" \ + "true" \ + "" \ + "%s" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "true" \ + "" \ + "" + +#define SOAP_AB_CONTACT_DEL_ACTION "http://www.msn.com/webservices/AddressBook/ABContactDelete" + +#define SOAP_AB_CONTACT_DEL_PAYLOAD \ + "" \ + "00000000-0000-0000-0000-000000000000" \ + "" \ + "" \ + "%s" \ + "" \ + "" \ + "" + int msn_soap_addressbook_request( struct im_connection *ic ); int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ); - +int msn_soap_ab_contact_add( struct im_connection *ic, bee_user_t *bu ); +int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ); #endif /* __SOAP_H__ */ diff --git a/protocols/msn/tables.c b/protocols/msn/tables.c index fd7eca41..191abe43 100644 --- a/protocols/msn/tables.c +++ b/protocols/msn/tables.c @@ -82,6 +82,8 @@ const struct msn_status_code msn_status_code_list[] = { 229, "Group name too long", 0 }, { 230, "Cannot remove that group", 0 }, { 231, "Invalid group", 0 }, + { 240, "ADL/RML command with corrupted payload", STATUS_FATAL }, + { 241, "ADL/RML command with invalid modification", STATUS_FATAL }, { 280, "Switchboard failed", STATUS_SB_FATAL }, { 281, "Transfer to switchboard failed", 0 }, -- cgit v1.2.3 From d97f51b59a3ac6d9557ebd1e42a45928fe064b4b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Aug 2010 00:23:23 +0100 Subject: Fix issues with logging in with huge SSO tickets (hilariously, the 1024- byte buffer was just one byte too short, resulting in a \r-terminated login line and the server waiting for the \n). Also using xt_find_path(). --- protocols/msn/msn_util.c | 3 +-- protocols/msn/ns.c | 2 +- protocols/msn/soap.c | 16 +++++++--------- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 84d68b8c..069e68b8 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -64,8 +64,7 @@ static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list ) strcpy( handle, handle_ ); if( ( domain = strchr( handle, '@' ) ) ) - *(domain - ++) = '\0'; + *(domain++) = '\0'; else return NULL; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 23b8f3b1..5bf07c3e 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -704,7 +704,7 @@ void msn_auth_got_passport_token( struct im_connection *ic, char *token ) md = ic->proto_data; { - char buf[1024]; + char buf[1536]; g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); msn_write( ic, buf, strlen( buf ) ); diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 13ef7e37..5d641542 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -202,9 +202,7 @@ static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer dat return XT_HANDLED; id += strlen( id ) - 1; if( *id == '1' && - ( p = node->parent ) && ( p = p->parent ) && - ( p = xt_find_node( p->children, "wst:RequestedProofToken" ) ) && - ( p = xt_find_node( p->children, "wst:BinarySecret" ) ) && + ( p = xt_find_path( node, "../../wst:RequestedProofToken/wst:BinarySecret" ) ) && p->text ) sd->secret = g_strdup( p->text ); @@ -476,8 +474,7 @@ static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; - if( ( p = node->parent ) && ( p = p->parent ) && - ( p = xt_find_node( p->children, "MemberRole" ) ) ) + if( ( p = xt_find_path( node, "../../MemberRole" ) ) ) role = p->text; if( ( p = xt_find_node( node->children, "PassportName" ) ) ) @@ -635,8 +632,7 @@ static xt_status msn_soap_addressbook_group( struct xt_node *node, gpointer data char *id = NULL, *name = NULL; struct msn_soap_req_data *soap_req = data; - if( ( p = node->parent ) && - ( p = xt_find_node( p->children, "groupId" ) ) ) + if( ( p = xt_find_path( node, "../groupId" ) ) ) id = p->text; if( ( p = xt_find_node( node->children, "name" ) ) ) @@ -656,8 +652,7 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; - if( ( p = node->parent ) && - ( p = xt_find_node( p->children, "contactId" ) ) ) + if( ( p = xt_find_path( node, "../contactId" ) ) ) id = p->text; if( ( p = xt_find_node( node->children, "contactType" ) ) ) type = p->text; @@ -675,6 +670,9 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da return XT_HANDLED; } + if( handle == NULL ) + return XT_HANDLED; + if( !( bu = bee_user_by_handle( ic->bee, ic, handle ) ) && !( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) return XT_HANDLED; -- cgit v1.2.3 From ff27648aee17e649cdd1e47f503271e4fccbff43 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Aug 2010 01:05:49 +0100 Subject: Read group info. --- protocols/msn/msn.c | 12 +++++++++--- protocols/msn/msn.h | 13 +++++++++---- protocols/msn/msn_util.c | 32 ++++++++++++++++++++++++++++++++ protocols/msn/soap.c | 18 +++++++++++++++++- 4 files changed, 67 insertions(+), 8 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 679ac65e..00c01dc3 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -106,14 +106,20 @@ static void msn_logout( struct im_connection *ic ) msn_msgq_purge( ic, &md->msgq ); - while( md->groupcount > 0 ) - g_free( md->grouplist[--md->groupcount] ); - g_free( md->grouplist ); g_free( md->tokens[0] ); g_free( md->tokens[1] ); g_free( md->tokens[2] ); g_free( md->lock_key ); + while( md->groups ) + { + struct msn_group *mg = md->groups->data; + g_free( mg->id ); + g_free( mg->name ); + g_free( mg ); + md->groups = g_slist_remove( md->groups, mg ); + } + g_tree_destroy( md->domaintree ); md->domaintree = NULL; diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 862d1ef7..c7529803 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -90,12 +90,9 @@ struct msn_data GSList *switchboards; int sb_failures; time_t first_sb_failure; - GSList *filetransfers; const struct msn_away_state *away_state; - int buddycount; - int groupcount; - char **grouplist; + GSList *groups; GTree *domaintree; }; @@ -174,6 +171,12 @@ struct msn_buddy_data msn_buddy_flags_t flags; }; +struct msn_group +{ + char *name; + char *id; +}; + /* Bitfield values for msn_status_code.flags */ #define STATUS_FATAL 1 #define STATUS_SB_FATAL 2 @@ -210,6 +213,8 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ); gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ); char *msn_p11_challenge( char *challenge ); gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ); +struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ); +struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 069e68b8..cf8ab4db 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -565,3 +565,35 @@ gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ) return ret; } + +struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ) +{ + struct msn_data *md = ic->proto_data; + GSList *l; + + for( l = md->groups; l; l = l->next ) + { + struct msn_group *mg = l->data; + + if( g_strcasecmp( mg->name, name ) == 0 ) + return mg; + } + + return NULL; +} + +struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ) +{ + struct msn_data *md = ic->proto_data; + GSList *l; + + for( l = md->groups; l; l = l->next ) + { + struct msn_group *mg = l->data; + + if( g_strcasecmp( mg->id, id ) == 0 ) + return mg; + } + + return NULL; +} diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 5d641542..b8762ce1 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -631,6 +631,7 @@ static xt_status msn_soap_addressbook_group( struct xt_node *node, gpointer data struct xt_node *p; char *id = NULL, *name = NULL; struct msn_soap_req_data *soap_req = data; + struct msn_data *md = soap_req->ic->proto_data; if( ( p = xt_find_path( node, "../groupId" ) ) ) id = p->text; @@ -638,6 +639,14 @@ static xt_status msn_soap_addressbook_group( struct xt_node *node, gpointer data if( ( p = xt_find_node( node->children, "name" ) ) ) name = p->text; + if( id && name ) + { + struct msn_group *mg = g_new0( struct msn_group, 1 ); + mg->id = g_strdup( id ); + mg->name = g_strdup( name ); + md->groups = g_slist_prepend( md->groups, mg ); + } + printf( "%s %s\n", id, name ); return XT_HANDLED; @@ -648,9 +657,11 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da bee_user_t *bu; struct msn_buddy_data *bd; struct xt_node *p; - char *id = NULL, *type = NULL, *handle = NULL, *display_name = NULL; + char *id = NULL, *type = NULL, *handle = NULL, + *display_name = NULL, *group_id = NULL; struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; + struct msn_group *group; if( ( p = xt_find_path( node, "../contactId" ) ) ) id = p->text; @@ -660,6 +671,8 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da handle = p->text; if( ( p = xt_find_node( node->children, "displayName" ) ) ) display_name = p->text; + if( ( p = xt_find_path( node, "groupIds/guid" ) ) ) + group_id = p->text; if( type && g_strcasecmp( type, "me" ) == 0 ) { @@ -684,6 +697,9 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da imcb_rename_buddy( ic, handle, display_name ); + if( group_id && ( group = msn_group_by_id( ic, group_id ) ) ) + imcb_add_buddy( ic, handle, group->name ); + printf( "%s %s %s %s\n", id, type, handle, display_name ); return XT_HANDLED; -- cgit v1.2.3 From 5a7af1ba940521a65b3611e5f96ffa9306497e45 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Aug 2010 14:02:52 +0100 Subject: The ADL command doesn't support >150 contacts. Split it up. --- protocols/msn/msn.h | 6 ++++ protocols/msn/ns.c | 88 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 66 insertions(+), 28 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index c7529803..f6666178 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -93,7 +93,12 @@ struct msn_data const struct msn_away_state *away_state; GSList *groups; + + /* Mostly used for sending the ADL command; since MSNP13 the client + is responsible for downloading the contact list and then sending + it to the MSNP server. */ GTree *domaintree; + int adl_todo; }; struct msn_switchboard @@ -163,6 +168,7 @@ typedef enum MSN_BUDDY_BL = 4, MSN_BUDDY_RL = 8, MSN_BUDDY_PL = 16, + MSN_BUDDY_ADL_SYNCED = 256, } msn_buddy_flags_t; struct msn_buddy_data diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 5bf07c3e..a599b0ba 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -34,6 +34,7 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); +static void msn_ns_send_adl_start( struct im_connection *ic ); static void msn_ns_send_adl( struct im_connection *ic ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) @@ -256,30 +257,32 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "BLP" ) == 0 ) { - msn_ns_send_adl( ic ); + msn_ns_send_adl_start( ic ); } else if( strcmp( cmd[0], "ADL" ) == 0 ) { if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 ) { - char buf[1024]; - char *fn_raw; - char *fn; + msn_ns_send_adl( ic ); - if( ic->flags & OPT_LOGGED_IN ) - return 1; - - if( ( fn_raw = set_getstr( &ic->acc->set, "display_name" ) ) == NULL ) - fn_raw = ic->acc->user; - fn = g_malloc( strlen( fn_raw ) * 3 + 1 ); - strcpy( fn, fn_raw ); - http_encode( fn ); - - g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", - ++md->trId, fn ); - g_free( fn ); - - msn_write( ic, buf, strlen( buf ) ); + if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) + { + char buf[1024]; + char *fn_raw; + char *fn; + + if( ( fn_raw = set_getstr( &ic->acc->set, "display_name" ) ) == NULL ) + fn_raw = ic->acc->user; + fn = g_malloc( strlen( fn_raw ) * 3 + 1 ); + strcpy( fn, fn_raw ); + http_encode( fn ); + + g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", + ++md->trId, fn ); + g_free( fn ); + + msn_write( ic, buf, strlen( buf ) ); + } } else if( num_parts >= 3 ) { @@ -732,11 +735,12 @@ static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) struct xt_node *adl = data, *d, *c; struct bee_user *bu = value; struct msn_buddy_data *bd = bu->data; + struct msn_data *md = bu->ic->proto_data; char handle[strlen(bu->handle)]; char *domain; char l[4]; - if( ( bd->flags & 7 ) == 0 ) + if( ( bd->flags & 7 ) == 0 || ( bd->flags & MSN_BUDDY_ADL_SYNCED ) ) return FALSE; strcpy( handle, bu->handle ); @@ -760,24 +764,27 @@ static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */ xt_insert_child( d, c ); - return FALSE; + /* Do this in batches of 100. */ + bd->flags |= MSN_BUDDY_ADL_SYNCED; + return (--md->adl_todo % 140) == 0; } static void msn_ns_send_adl( struct im_connection *ic ) { struct xt_node *adl; - struct msn_data *md; + struct msn_data *md = ic->proto_data; char *adls, buf[64]; - /* Dead connection? */ - if( g_slist_find( msn_connections, ic ) == NULL ) - return; - - md = ic->proto_data; - adl = xt_new_node( "ml", NULL, NULL ); xt_add_attr( adl, "l", "1" ); g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl ); + if( adl->children == NULL ) + { + /* This tells the caller that we're done now. */ + md->adl_todo = -1; + xt_free_node( adl ); + return; + } adls = xt_to_string( adl ); g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) ); @@ -785,5 +792,30 @@ static void msn_ns_send_adl( struct im_connection *ic ) msn_write( ic, adls, strlen( adls ) ); g_free( adls ); - xt_free_node( adl ); +} + +static void msn_ns_send_adl_start( struct im_connection *ic ) +{ + struct msn_data *md; + GSList *l; + + /* Dead connection? */ + if( g_slist_find( msn_connections, ic ) == NULL ) + return; + + md = ic->proto_data; + md->adl_todo = 0; + for( l = ic->bee->users; l; l = l->next ) + { + bee_user_t *bu = l->data; + struct msn_buddy_data *bd = bu->data; + + if( bu->ic != ic || ( bd->flags & 7 ) == 0 ) + continue; + + bd->flags &= ~MSN_BUDDY_ADL_SYNCED; + md->adl_todo++; + } + + msn_ns_send_adl( ic ); } -- cgit v1.2.3 From 660cb00687dbe0abd37e705a2923d1cf8bf6f45c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Aug 2010 14:23:03 +0100 Subject: Parse authentication errors. --- protocols/msn/msn.h | 2 +- protocols/msn/ns.c | 8 +++++++- protocols/msn/soap.c | 27 ++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index f6666178..ae4ea42b 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -203,7 +203,7 @@ extern GSList *msn_switchboards; /* ns.c */ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); -void msn_auth_got_passport_token( struct im_connection *ic, char *token ); +void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ); void msn_auth_got_contact_list( struct im_connection *ic ); /* msn_util.c */ diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index a599b0ba..2449c8d5 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -696,7 +696,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int return( 1 ); } -void msn_auth_got_passport_token( struct im_connection *ic, char *token ) +void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ) { struct msn_data *md; @@ -706,12 +706,18 @@ void msn_auth_got_passport_token( struct im_connection *ic, char *token ) md = ic->proto_data; + if( token ) { char buf[1536]; g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); msn_write( ic, buf, strlen( buf ) ); } + else + { + imcb_error( ic, "Error during Passport authentication: %s", error ); + imc_logout( ic, TRUE ); + } } void msn_auth_got_contact_list( struct im_connection *ic ) diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index b8762ce1..fe716d9d 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -172,6 +172,7 @@ struct msn_soap_passport_sso_data char *policy; char *nonce; char *secret; + char *error; }; static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req ) @@ -216,8 +217,25 @@ static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer dat return XT_HANDLED; } +static xt_status msn_soap_passport_failure( struct xt_node *node, gpointer data ) +{ + struct msn_soap_req_data *soap_req = data; + struct msn_soap_passport_sso_data *sd = soap_req->data; + struct xt_node *code = xt_find_node( node->children, "faultcode" ); + struct xt_node *string = xt_find_node( node->children, "faultstring" ); + + if( code == NULL || code->text_len == 0 ) + sd->error = g_strdup( "Unknown error" ); + else + sd->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ? + string->text : "no description available" ); + + return XT_HANDLED; +} + static const struct xt_handler_entry msn_soap_passport_sso_parser[] = { { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", msn_soap_passport_sso_token }, + { "S:Fault", "S:Envelope", msn_soap_passport_failure }, { NULL, NULL, NULL } }; @@ -269,6 +287,12 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap GUINT32_TO_LE( 20 ), GUINT32_TO_LE( 72 ), }; + + if( sd->secret == NULL ) + { + msn_auth_got_passport_token( ic, NULL, sd->error ); + return MSN_SOAP_OK; + } key1_len = base64_decode( sd->secret, (unsigned char**) &key1 ); @@ -286,7 +310,7 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap memcpy( blurb.cipherbytes, des3res, 72 ); blurb64 = base64_encode( (unsigned char*) &blurb, sizeof( blurb ) ); - msn_auth_got_passport_token( ic, blurb64 ); + msn_auth_got_passport_token( ic, blurb64, NULL ); g_free( padnonce ); g_free( blurb64 ); @@ -305,6 +329,7 @@ static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req ) g_free( sd->policy ); g_free( sd->nonce ); g_free( sd->secret ); + g_free( sd->error ); return MSN_SOAP_OK; } -- cgit v1.2.3 From 9679fd8f3141abb0cabe7b036cf96c3de40ee22a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Aug 2010 15:27:44 +0100 Subject: Removing soap.h dependency in Makefile. I'll have to fix the internal dependencies for real some day soon, but this one-off hack is breaking out-of-tree builds. --- protocols/msn/Makefile | 2 -- 1 file changed, 2 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index a14225d1..8ff61c60 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -41,5 +41,3 @@ $(objects): %.o: $(SRCDIR)%.c msn_mod.o: $(objects) @echo '*' Linking msn_mod.o @$(LD) $(LFLAGS) $(objects) -o msn_mod.o - -soap.o: soap.h soap.c -- cgit v1.2.3 From 9b01339168bc79d08c4e371552cc44648bd8878d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Aug 2010 18:19:06 +0100 Subject: Check the flag in address book entries, ignore the ones that have it set to false, or this code will add all non-Messenger contacts to the contact list (oops). --- protocols/msn/soap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index fe716d9d..91f93afd 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -682,7 +682,7 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da bee_user_t *bu; struct msn_buddy_data *bd; struct xt_node *p; - char *id = NULL, *type = NULL, *handle = NULL, + char *id = NULL, *type = NULL, *handle = NULL, *is_msgr = "false", *display_name = NULL, *group_id = NULL; struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; @@ -696,6 +696,8 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da handle = p->text; if( ( p = xt_find_node( node->children, "displayName" ) ) ) display_name = p->text; + if( ( p = xt_find_node( node->children, "isMessengerUser" ) ) ) + is_msgr = p->text; if( ( p = xt_find_path( node, "groupIds/guid" ) ) ) group_id = p->text; @@ -708,7 +710,7 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da return XT_HANDLED; } - if( handle == NULL ) + if( !bool2int( is_msgr ) || handle == NULL ) return XT_HANDLED; if( !( bu = bee_user_by_handle( ic->bee, ic, handle ) ) && -- cgit v1.2.3 From e0e15468835d5ae5bce54a28bd7a5b7aea66a1e2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Aug 2010 19:46:10 +0100 Subject: Making display name code a bit saner. Apparently PoS MSN is still suffering from display_name amnesia a little bit though at least with Hotmail accounts. --- protocols/msn/msn.c | 15 +-------------- protocols/msn/msn.h | 2 +- protocols/msn/msn_util.c | 16 ++++++++++++++++ protocols/msn/ns.c | 20 ++++++-------------- protocols/msn/soap.c | 7 ++++++- 5 files changed, 30 insertions(+), 30 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 00c01dc3..873a51ad 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -336,9 +336,6 @@ static char *set_eval_display_name( set_t *set, char *value ) { account_t *acc = set->data; struct im_connection *ic = acc->ic; - struct msn_data *md = ic->proto_data; - char buf[512]; - char *fn; if( strlen( value ) > 129 ) { @@ -347,17 +344,7 @@ static char *set_eval_display_name( set_t *set, char *value ) } msn_soap_addressbook_set_display_name( ic, value ); - - fn = g_malloc( strlen( value ) * 3 + 1 ); - strcpy( fn, value ); - http_encode( fn ); - g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", - ++md->trId, fn ); - g_free( fn ); - - /* Note: We don't actually know if the server accepted the new name, - and won't give proper feedback yet if it doesn't. */ - return msn_write( ic, buf, strlen( buf ) ) ? value : NULL; + return msn_ns_set_display_name( ic, value ) ? value : NULL; } static void msn_buddy_data_add( bee_user_t *bu ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index ae4ea42b..3ea8c503 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -216,11 +216,11 @@ char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); void msn_msgq_purge( struct im_connection *ic, GSList **list ); -gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ); char *msn_p11_challenge( char *challenge ); gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ); struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ); struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ); +int msn_ns_set_display_name( struct im_connection *ic, const char *value ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index cf8ab4db..78f81a41 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -597,3 +597,19 @@ struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ) return NULL; } + +int msn_ns_set_display_name( struct im_connection *ic, const char *value ) +{ + struct msn_data *md = ic->proto_data; + char fn[strlen(value)*3+1]; + char buf[512]; + + strcpy( fn, value ); + http_encode( fn ); + g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", + ++md->trId, fn ); + + /* Note: We don't actually know if the server accepted the new name, + and won't give proper feedback yet if it doesn't. */ + return msn_write( ic, buf, strlen( buf ) ); +} diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 2449c8d5..c9b01ef2 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -258,6 +258,9 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) else if( strcmp( cmd[0], "BLP" ) == 0 ) { msn_ns_send_adl_start( ic ); + + if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) + return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); } else if( strcmp( cmd[0], "ADL" ) == 0 ) { @@ -267,21 +270,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) { - char buf[1024]; - char *fn_raw; - char *fn; - - if( ( fn_raw = set_getstr( &ic->acc->set, "display_name" ) ) == NULL ) - fn_raw = ic->acc->user; - fn = g_malloc( strlen( fn_raw ) * 3 + 1 ); - strcpy( fn, fn_raw ); - http_encode( fn ); - - g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", - ++md->trId, fn ); - g_free( fn ); + msn_ns_send_adl( ic ); - msn_write( ic, buf, strlen( buf ) ); + if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) + return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); } } else if( num_parts >= 3 ) diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 91f93afd..b717343f 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -686,6 +686,7 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da *display_name = NULL, *group_id = NULL; struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; + struct msn_data *md = soap_req->ic->proto_data; struct msn_group *group; if( ( p = xt_find_path( node, "../contactId" ) ) ) @@ -703,6 +704,10 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da if( type && g_strcasecmp( type, "me" ) == 0 ) { +#if 0 + g_free( md->myid ); + md->myid = g_strdup( id ); +#endif set_t *set = set_find( &ic->acc->set, "display_name" ); g_free( set->value ); set->value = g_strdup( display_name ); @@ -765,7 +770,7 @@ static int msn_soap_ab_namechange_build_request( struct msn_soap_req_data *soap_ soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); soap_req->action = g_strdup( SOAP_AB_NAMECHANGE_ACTION ); soap_req->payload = msn_soap_abservice_build( SOAP_AB_NAMECHANGE_PAYLOAD, - "Initial", md->tokens[1], (char *) soap_req->data ); + "Timer", md->tokens[1], (char *) soap_req->data ); return 1; } -- cgit v1.2.3 From 80175a1558f297d5505ed4e91a261781ec9c65a2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 18 Aug 2010 20:21:44 +0100 Subject: Fetch the user's profile to see if there's a display name set there. If there is, the one in the address book should be ignored. No support for changing the profile yet though. --- protocols/msn/msn.c | 11 +++++--- protocols/msn/msn.h | 14 +++++++--- protocols/msn/ns.c | 29 ++++++++++++-------- protocols/msn/soap.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++----- protocols/msn/soap.h | 57 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 163 insertions(+), 24 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 873a51ad..4b79cc26 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -82,6 +82,7 @@ static void msn_logout( struct im_connection *ic ) { struct msn_data *md = ic->proto_data; GSList *l; + int i; if( md ) { @@ -106,9 +107,8 @@ static void msn_logout( struct im_connection *ic ) msn_msgq_purge( ic, &md->msgq ); - g_free( md->tokens[0] ); - g_free( md->tokens[1] ); - g_free( md->tokens[2] ); + for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ ) + g_free( md->tokens[i] ); g_free( md->lock_key ); while( md->groups ) @@ -336,6 +336,7 @@ static char *set_eval_display_name( set_t *set, char *value ) { account_t *acc = set->data; struct im_connection *ic = acc->ic; + struct msn_data *md = ic->proto_data; if( strlen( value ) > 129 ) { @@ -343,6 +344,10 @@ static char *set_eval_display_name( set_t *set, char *value ) return NULL; } + if( md->flags & MSN_GOT_PROFILE_DN ) + imcb_log( ic, "Warning: Persistent name changes for this account have to be done " + "in the profile. BitlBee doesn't currently support this." ); + msn_soap_addressbook_set_display_name( ic, value ); return msn_ns_set_display_name( ic, value ) ? value : NULL; } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 3ea8c503..7cb3241c 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -49,12 +49,9 @@ */ #define MSNP11_PROD_KEY "ILTXC!4IXB5FB*PX" -//PK}_A_0N_K%O?A9S" #define MSNP11_PROD_ID "PROD0119GSJUC$18" -//PROD0114ES4Z%Q5W" #define MSNP_VER "MSNP15" #define MSNP_BUILD "8.5.1288" -//"8.1.0178" #define MSN_SB_NEW -24062002 @@ -75,15 +72,23 @@ #define PROFILE_URL "http://members.msn.com/" +typedef enum +{ + MSN_GOT_PROFILE = 1, + MSN_GOT_PROFILE_DN = 2, + MSN_DONE_ADL = 4, +} msn_flags_t; + struct msn_data { struct im_connection *ic; int fd; struct msn_handler_data *handler; + msn_flags_t flags; int trId; - char *tokens[3]; + char *tokens[4]; char *lock_key; GSList *msgq, *grpq; @@ -205,6 +210,7 @@ extern GSList *msn_switchboards; gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ); void msn_auth_got_contact_list( struct im_connection *ic ); +int msn_ns_finish_login( struct im_connection *ic ); /* msn_util.c */ int msn_write( struct im_connection *ic, char *s, int len ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index c9b01ef2..4b779a58 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -258,23 +258,14 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) else if( strcmp( cmd[0], "BLP" ) == 0 ) { msn_ns_send_adl_start( ic ); - - if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) - return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); + return msn_ns_finish_login( ic ); } else if( strcmp( cmd[0], "ADL" ) == 0 ) { if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 ) { msn_ns_send_adl( ic ); - - if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) - { - msn_ns_send_adl( ic ); - - if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) - return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); - } + return msn_ns_finish_login( ic ); } else if( num_parts >= 3 ) { @@ -817,3 +808,19 @@ static void msn_ns_send_adl_start( struct im_connection *ic ) msn_ns_send_adl( ic ); } + +int msn_ns_finish_login( struct im_connection *ic ) +{ + struct msn_data *md = ic->proto_data; + + if( ic->flags & OPT_LOGGED_IN ) + return 1; + + if( md->adl_todo < 0 ) + md->flags |= MSN_DONE_ADL; + + if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) ) + return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); + else + return 1; +} diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index b717343f..410ff37c 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -208,7 +208,7 @@ static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer dat sd->secret = g_strdup( p->text ); *id -= '1'; - if( *id >= 0 && *id <= 2 ) + if( *id >= 0 && *id < sizeof( md->tokens ) / sizeof( md->tokens[0] ) ) { g_free( md->tokens[(int)*id] ); md->tokens[(int)*id] = g_strdup( node->text ); @@ -686,7 +686,6 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da *display_name = NULL, *group_id = NULL; struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; - struct msn_data *md = soap_req->ic->proto_data; struct msn_group *group; if( ( p = xt_find_path( node, "../contactId" ) ) ) @@ -704,14 +703,15 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da if( type && g_strcasecmp( type, "me" ) == 0 ) { -#if 0 - g_free( md->myid ); - md->myid = g_strdup( id ); -#endif set_t *set = set_find( &ic->acc->set, "display_name" ); g_free( set->value ); set->value = g_strdup( display_name ); + /* Try to fetch the profile; if the user has one, that's where + we can find the persistent display_name. */ + if( ( p = xt_find_node( node->children, "CID" ) ) && p->text ) + msn_soap_profile_get( ic, p->text ); + return XT_HANDLED; } @@ -881,3 +881,67 @@ int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ) msn_soap_ab_contact_del_handle_response, msn_soap_ab_contact_del_free_data ); } + + + +/* Storage stuff: Fetch profile. */ +static int msn_soap_profile_get_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + + soap_req->url = g_strdup( SOAP_STORAGE_URL ); + soap_req->action = g_strdup( SOAP_PROFILE_GET_ACTION ); + soap_req->payload = g_markup_printf_escaped( SOAP_PROFILE_GET_PAYLOAD, + md->tokens[3], (char*) soap_req->data ); + + return 1; +} + +static xt_status msn_soap_profile_get_result( struct xt_node *node, gpointer data ) +{ + struct msn_soap_req_data *soap_req = data; + struct im_connection *ic = soap_req->ic; + struct msn_data *md = soap_req->ic->proto_data; + struct xt_node *dn; + + if( ( dn = xt_find_node( node->children, "DisplayName" ) ) && dn->text ) + { + set_t *set = set_find( &ic->acc->set, "display_name" ); + g_free( set->value ); + set->value = g_strdup( dn->text ); + + md->flags |= MSN_GOT_PROFILE_DN; + } + + return XT_HANDLED; +} + +static const struct xt_handler_entry msn_soap_profile_get_parser[] = { + { "ExpressionProfile", "GetProfileResult", msn_soap_profile_get_result }, + { NULL, NULL, NULL } +}; + +static int msn_soap_profile_get_handle_response( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + + md->flags |= MSN_GOT_PROFILE; + msn_ns_finish_login( soap_req->ic ); + + return MSN_SOAP_OK; +} + +static int msn_soap_profile_get_free_data( struct msn_soap_req_data *soap_req ) +{ + g_free( soap_req->data ); + return 0; +} + +int msn_soap_profile_get( struct im_connection *ic, const char *cid ) +{ + return msn_soap_start( ic, g_strdup( cid ), + msn_soap_profile_get_build_request, + msn_soap_profile_get_parser, + msn_soap_profile_get_handle_response, + msn_soap_profile_get_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 19a5c6ae..9fba5366 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -125,6 +125,15 @@ "" \ "" \ "" \ + "" \ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ + "" \ + "" \ + "storage.msn.com" \ + "" \ + "" \ + "" \ + "" \ "" \ "" \ "" @@ -286,4 +295,52 @@ int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char int msn_soap_ab_contact_add( struct im_connection *ic, bee_user_t *bu ); int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ); + +#define SOAP_STORAGE_URL "https://storage.msn.com/storageservice/SchematizedStore.asmx" +#define SOAP_PROFILE_GET_ACTION "http://www.msn.com/webservices/storage/w10/GetProfile" + +#define SOAP_PROFILE_GET_PAYLOAD \ +"" \ +"" \ + "" \ + "" \ + "Messenger Client 9.0" \ + "Initial" \ + "" \ + "" \ + "0" \ + "%s" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "%s" \ + "MyCidStuff" \ + "" \ + "MyProfile" \ + "" \ + "" \ + "true" \ + "true" \ + "" \ + "true" \ + "true" \ + "true" \ + "true" \ + "true" \ + "true" \ + "true" \ + "true" \ + "true" \ + "" \ + "" \ + "" \ + "" \ +"" + +int msn_soap_profile_get( struct im_connection *ic, const char *cid ); + + #endif /* __SOAP_H__ */ -- cgit v1.2.3 From f2520b5ad5a82d9bf08a550fb0e49913f57d4685 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 20 Aug 2010 09:22:28 +0100 Subject: In debugging mode, dump all SOAP requests + responses with some indentation for easier debugging. --- protocols/msn/soap.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 410ff37c..6665eef1 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -67,6 +67,7 @@ struct msn_soap_req_data }; static int msn_soap_send_request( struct msn_soap_req_data *req ); +static void msn_soap_debug_print( const char *headers, const char *payload ); static int msn_soap_start( struct im_connection *ic, void *data, @@ -106,6 +107,8 @@ static int msn_soap_send_request( struct msn_soap_req_data *soap_req ) soap_action ? soap_action : "", strlen( soap_req->payload ), soap_req->payload ); + msn_soap_debug_print( http_req, soap_req->payload ); + soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS, http_req, msn_soap_handle_response, soap_req ); @@ -130,6 +133,8 @@ static void msn_soap_handle_response( struct http_request *http_req ) xt_free( parser ); } + msn_soap_debug_print( http_req->reply_headers, http_req->reply_body ); + st = soap_req->handle_response( soap_req ); g_free( soap_req->url ); @@ -164,6 +169,28 @@ static char *msn_soap_abservice_build( const char *body_fmt, const char *scenari return ret; } +static void msn_soap_debug_print( const char *headers, const char *payload ) +{ + char *s; + + if( !getenv( "BITLBEE_DEBUG" ) ) + return; + + if( ( s = strstr( headers, "\r\n\r\n" ) ) ) + write( 1, s, s - headers + 4 ); + else + write( 1, headers, strlen( headers ) ); + +#ifdef DEBUG + { + struct xt_node *xt = xt_from_string( payload ); + if( xt ) + xt_print( xt ); + xt_free_node( xt ); + } +#endif +} + /* passport_sso: Authentication MSNP15+ */ -- cgit v1.2.3 From 801b90b3e76f6eed7027f46a7d11e3d3fe0e04e9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 20 Aug 2010 20:30:12 +0100 Subject: Check if a connection is down before handling its SOAP responses. --- protocols/msn/soap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 6665eef1..e67da2a1 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -123,6 +123,16 @@ static void msn_soap_handle_response( struct http_request *http_req ) struct msn_soap_req_data *soap_req = http_req->data; int st; + if( g_slist_find( msn_connections, soap_req->ic ) == NULL ) + { + soap_req->free_data( soap_req ); + g_free( soap_req->url ); + g_free( soap_req->action ); + g_free( soap_req->payload ); + g_free( soap_req ); + return; + } + if( http_req->body_size > 0 ) { struct xt_parser *parser; -- cgit v1.2.3 From 327af51a28fe292cfc4a68caa086a13175a69719 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 21 Aug 2010 18:27:32 +0100 Subject: Some general cleanup, plus fixing a bug in the memberlist parsing code: the lists can come in in any order, so parse it *completely* before showing auth requests. --- protocols/msn/soap.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index e67da2a1..8d276108 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -553,17 +553,11 @@ static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) else if( strcmp( role, "Block" ) == 0 ) bd->flags |= MSN_BUDDY_BL; else if( strcmp( role, "Reverse" ) == 0 ) - { bd->flags |= MSN_BUDDY_RL; - msn_buddy_ask( bu ); - } else if( strcmp( role, "Pending" ) == 0 ) - { bd->flags |= MSN_BUDDY_PL; - msn_buddy_ask( bu ); - } - printf( "%s %d\n", handle, bd->flags ); + printf( "%p %s %d\n", bu, handle, bd->flags ); return XT_HANDLED; } @@ -782,7 +776,18 @@ static const struct xt_handler_entry msn_soap_addressbook_parser[] = { static int msn_soap_addressbook_handle_response( struct msn_soap_req_data *soap_req ) { + GSList *l; + + for( l = soap_req->ic->bee->users; l; l = l->next ) + { + struct bee_user *bu = l->data; + + if( bu->ic == soap_req->ic ) + msn_buddy_ask( bu ); + } + msn_auth_got_contact_list( soap_req->ic ); + return MSN_SOAP_OK; } -- cgit v1.2.3 From fd424c891db6da587cce3da8ac98ab7dfa986fb3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 22 Aug 2010 00:08:33 +0100 Subject: Also pick up MSN Messenger mobile info. --- protocols/msn/ns.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 4b779a58..bd13c3a6 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -332,8 +332,9 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) else if( strcmp( cmd[0], "NLN" ) == 0 ) { const struct msn_away_state *st; + int cap; - if( num_parts < 5 ) + if( num_parts < 6 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); @@ -341,6 +342,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } http_decode( cmd[4] ); + cap = atoi( cmd[5] ); imcb_rename_buddy( ic, cmd[2], cmd[4] ); st = msn_away_state_by_code( cmd[1] ); @@ -351,7 +353,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | - ( st != msn_away_state_list ? OPT_AWAY : 0 ), + ( st != msn_away_state_list ? OPT_AWAY : 0 ) | + ( cap & 1 ? OPT_MOBILE : 0 ), st->name, NULL ); msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) ); -- cgit v1.2.3 From 9b1d2d6fa7edb911e3dbcd8785aaa797ebb20d0a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 22 Aug 2010 11:42:27 +0100 Subject: Ignore empty status messages, and msnmsgrp2p invitations. --- protocols/bee_user.c | 2 +- protocols/msn/sb.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/bee_user.c b/protocols/bee_user.c index 71b15d29..1f9b1b47 100644 --- a/protocols/bee_user.c +++ b/protocols/bee_user.c @@ -222,7 +222,7 @@ void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const old = g_memdup( bu, sizeof( bee_user_t ) ); - bu->status_msg = g_strdup( message ); + bu->status_msg = message && *message ? g_strdup( message ) : NULL; if( bee->ui->user_status ) bee->ui->user_status( bee, bu, old ); diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index fdad2882..75417fae 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -751,8 +751,8 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int #endif else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 ) { - imcb_error( sb->ic, "Cannot receive file from %s: BitlBee does not " - "support msnmsgrp2p yet.", sb->who ); + /* Not currently implemented. Don't warn about it since + this seems to be used for avatars now. */ g_free( ct ); } else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 ) -- cgit v1.2.3 From 00374acf3061c2c6c34fd2eda42e452211f7c4f9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 28 Aug 2010 14:22:50 +0200 Subject: Don't treat error 241 as fatal since it isn't - or at least not always. --- protocols/msn/tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/msn/tables.c b/protocols/msn/tables.c index 191abe43..273d291e 100644 --- a/protocols/msn/tables.c +++ b/protocols/msn/tables.c @@ -83,7 +83,7 @@ const struct msn_status_code msn_status_code_list[] = { 230, "Cannot remove that group", 0 }, { 231, "Invalid group", 0 }, { 240, "ADL/RML command with corrupted payload", STATUS_FATAL }, - { 241, "ADL/RML command with invalid modification", STATUS_FATAL }, + { 241, "ADL/RML command with invalid modification", 0 }, { 280, "Switchboard failed", STATUS_SB_FATAL }, { 281, "Transfer to switchboard failed", 0 }, -- cgit v1.2.3 From 02bb9db2edd535036e030e004a58ed1459c15bb8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 29 Aug 2010 11:39:27 +0200 Subject: Handle payloads attached to errors (assume any number in cmd[2] would be a payload length, which seems like a fair assumption). This should solve problems with logging in with dodgy contact/membership lists. --- protocols/msn/ns.c | 4 ++++ protocols/nogaim.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index bd13c3a6..fa445aa7 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -518,6 +518,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imc_logout( ic, TRUE ); return( 0 ); } + + /* Oh yes, errors can have payloads too now. Discard them for now. */ + if( num_parts >= 3 ) + md->handler->msglen = atoi( cmd[2] ); } else { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 10ffd843..aa3ad5bb 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -251,7 +251,7 @@ void imcb_error( struct im_connection *ic, char *format, ... ) if( ic->flags & OPT_LOGGED_IN ) serv_got_crap( ic, "Error: %s", text ); else - serv_got_crap( ic, "Couldn't log in: %s", text ); + serv_got_crap( ic, "Login error: %s", text ); g_free( text ); } -- cgit v1.2.3 From 64768d4ec0c3ad473573c3f3c34871e0081b4e59 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 2 Sep 2010 10:15:44 +0100 Subject: Replace msn*write functions with saner versions that accept format strings. Also preparing for additional temporary NS connections (auth token renewal). --- protocols/msn/msn.c | 14 ++++----- protocols/msn/msn.h | 4 +-- protocols/msn/msn_util.c | 43 ++++++--------------------- protocols/msn/ns.c | 75 +++++++++++++++++++++++++++++------------------- protocols/msn/sb.c | 57 ++++++++++++++++-------------------- 5 files changed, 87 insertions(+), 106 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 4b79cc26..f37b802e 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -153,8 +153,7 @@ static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, in #ifdef DEBUG if( strcmp( who, "raw" ) == 0 ) { - msn_write( ic, message, strlen( message ) ); - msn_write( ic, "\r\n", 2 ); + msn_ns_write( ic, -1, "%s\r\n", message ); } else #endif @@ -192,7 +191,6 @@ static GList *msn_away_states( struct im_connection *ic ) static void msn_set_away( struct im_connection *ic, char *state, char *message ) { - char buf[1024]; char *uux; struct msn_data *md = ic->proto_data; @@ -201,15 +199,13 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL ) md->away_state = msn_away_state_list + 1; - g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, md->away_state->code ); - if( !msn_write( ic, buf, strlen( buf ) ) ) + if( !msn_ns_write( ic, -1, "CHG %d %s\r\n", ++md->trId, md->away_state->code ) ) return; uux = g_markup_printf_escaped( "%s" "", message ? message : "" ); - g_snprintf( buf, sizeof( buf ), "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); - if( !msn_write( ic, buf, strlen( buf ) ) ) - return; + msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); + g_free( uux ); } static void msn_get_info(struct im_connection *ic, char *who) @@ -289,7 +285,7 @@ static struct groupchat *msn_chat_with( struct im_connection *ic, char *who ) static void msn_keepalive( struct im_connection *ic ) { - msn_write( ic, "PNG\r\n", strlen( "PNG\r\n" ) ); + msn_ns_write( ic, -1, "PNG\r\n" ); } static void msn_add_permit( struct im_connection *ic, char *who ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 7cb3241c..dae115ef 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -207,13 +207,13 @@ extern GSList *msn_connections; extern GSList *msn_switchboards; /* ns.c */ +int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ); void msn_auth_got_contact_list( struct im_connection *ic ); int msn_ns_finish_login( struct im_connection *ic ); /* msn_util.c */ -int msn_write( struct im_connection *ic, char *s, int len ); int msn_logged_in( struct im_connection *ic ); int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group ); int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ); @@ -235,7 +235,7 @@ const struct msn_away_state *msn_away_state_by_name( char *name ); const struct msn_status_code *msn_status_by_number( int number ); /* sb.c */ -int msn_sb_write( struct msn_switchboard *sb, char *s, int len ); +int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ); struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ); struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ); struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 78f81a41..6a16ba17 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -29,28 +29,6 @@ #include "soap.h" #include -int msn_write( struct im_connection *ic, char *s, int len ) -{ - struct msn_data *md = ic->proto_data; - int st; - - if( getenv( "BITLBEE_DEBUG" ) ) - { - write( 2, "->NS:", 5 ); - write( 2, s, len ); - } - - st = write( md->fd, s, len ); - if( st != len ) - { - imcb_error( ic, "Short write() to main server" ); - imc_logout( ic, TRUE ); - return 0; - } - - return 1; -} - int msn_logged_in( struct im_connection *ic ) { imcb_connected( ic ); @@ -75,7 +53,7 @@ static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list ) int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group ) { struct msn_data *md = ic->proto_data; - char buf[1024], groupid[8]; + char groupid[8]; bee_user_t *bu; struct msn_buddy_data *bd; char *adl; @@ -143,11 +121,11 @@ int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const if( ( adl = adlrml_entry( who, list ) ) ) { - g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n%s", - ++md->trId, strlen( adl ), adl ); + int st = msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", + ++md->trId, strlen( adl ), adl ); g_free( adl ); - return msn_write( ic, buf, strlen( buf ) ); + return st; } return 1; @@ -156,7 +134,7 @@ int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ) { struct msn_data *md = ic->proto_data; - char buf[1024], groupid[8]; + char groupid[8]; bee_user_t *bu; struct msn_buddy_data *bd; char *adl; @@ -188,11 +166,11 @@ int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, con if( ( adl = adlrml_entry( who, list ) ) ) { - g_snprintf( buf, sizeof( buf ), "RML %d %zd\r\n%s", - ++md->trId, strlen( adl ), adl ); + int st = msn_ns_write( ic, -1, "RML %d %zd\r\n%s", + ++md->trId, strlen( adl ), adl ); g_free( adl ); - return msn_write( ic, buf, strlen( buf ) ); + return st; } return 1; @@ -602,14 +580,11 @@ int msn_ns_set_display_name( struct im_connection *ic, const char *value ) { struct msn_data *md = ic->proto_data; char fn[strlen(value)*3+1]; - char buf[512]; strcpy( fn, value ); http_encode( fn ); - g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", - ++md->trId, fn ); /* Note: We don't actually know if the server accepted the new name, and won't give proper feedback yet if it doesn't. */ - return msn_write( ic, buf, strlen( buf ) ); + return msn_ns_write( ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn ); } diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index fa445aa7..23a1951d 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -37,11 +37,41 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int static void msn_ns_send_adl_start( struct im_connection *ic ); static void msn_ns_send_adl( struct im_connection *ic ); +int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) +{ + struct msn_data *md = ic->proto_data; + va_list params; + char *out; + size_t len; + int st; + + va_start( params, fmt ); + out = g_strdup_vprintf( fmt, params ); + va_end( params ); + + if( fd < 0 ) + fd = md->fd; + + if( getenv( "BITLBEE_DEBUG" ) ) + fprintf( stderr, "->NS%d:%s", fd, out ); + + len = strlen( out ); + st = write( fd, out, len ); + g_free( out ); + if( st != len ) + { + imcb_error( ic, "Short write() to main server" ); + imc_logout( ic, TRUE ); + return 0; + } + + return 1; +} + gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { struct im_connection *ic = data; struct msn_data *md; - char s[1024]; if( !g_slist_find( msn_connections, ic ) ) return FALSE; @@ -73,8 +103,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) md->handler->fd = md->fd; md->handler->rxq = g_new0( char, 1 ); - g_snprintf( s, sizeof( s ), "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ); - if( msn_write( ic, s, strlen( s ) ) ) + if( msn_ns_write( ic, -1, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) { ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); imcb_log( ic, "Connected to server, waiting for reply" ); @@ -103,7 +132,6 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { struct im_connection *ic = data; struct msn_data *md = ic->proto_data; - char buf[1024]; if( num_parts == 0 ) { @@ -120,15 +148,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } - g_snprintf( buf, sizeof( buf ), "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", - ++md->trId, ic->acc->user ); - return( msn_write( ic, buf, strlen( buf ) ) ); + return( msn_ns_write( ic, -1, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", + ++md->trId, ic->acc->user ) ); } else if( strcmp( cmd[0], "CVR" ) == 0 ) { /* We don't give a damn about the information we just received */ - g_snprintf( buf, sizeof( buf ), "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); - return( msn_write( ic, buf, strlen( buf ) ) ); + return msn_ns_write( ic, -1, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); } else if( strcmp( cmd[0], "XFR" ) == 0 ) { @@ -279,6 +305,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) else if( strcmp( cmd[0], "CHL" ) == 0 ) { char *resp; + int st; if( num_parts < 3 ) { @@ -288,12 +315,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } resp = msn_p11_challenge( cmd[2] ); - g_snprintf( buf, sizeof( buf ), "QRY %d %s %zd\r\n%s", - ++md->trId, MSNP11_PROD_ID, - strlen( resp ), resp ); - g_free( resp ); - return( msn_write( ic, buf, strlen( buf ) ) ); + st = msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s", + ++md->trId, MSNP11_PROD_ID, + strlen( resp ), resp ); + g_free( resp ); + return st; } else if( strcmp( cmd[0], "ILN" ) == 0 ) { @@ -698,10 +725,7 @@ void msn_auth_got_passport_token( struct im_connection *ic, const char *token, c if( token ) { - char buf[1536]; - - g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); - msn_write( ic, buf, strlen( buf ) ); + msn_ns_write( ic, -1, "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); } else { @@ -712,7 +736,6 @@ void msn_auth_got_passport_token( struct im_connection *ic, const char *token, c void msn_auth_got_contact_list( struct im_connection *ic ) { - char buf[64]; struct msn_data *md; /* Dead connection? */ @@ -720,10 +743,7 @@ void msn_auth_got_contact_list( struct im_connection *ic ) return; md = ic->proto_data; - - - g_snprintf( buf, sizeof( buf ), "BLP %d %s\r\n", ++md->trId, "BL" ); - msn_write( ic, buf, strlen( buf ) ); + msn_ns_write( ic, -1, "BLP %d %s\r\n", ++md->trId, "BL" ); } static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) @@ -769,7 +789,7 @@ static void msn_ns_send_adl( struct im_connection *ic ) { struct xt_node *adl; struct msn_data *md = ic->proto_data; - char *adls, buf[64]; + char *adls; adl = xt_new_node( "ml", NULL, NULL ); xt_add_attr( adl, "l", "1" ); @@ -781,12 +801,9 @@ static void msn_ns_send_adl( struct im_connection *ic ) xt_free_node( adl ); return; } - adls = xt_to_string( adl ); - - g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) ); - if( msn_write( ic, buf, strlen( buf ) ) ) - msn_write( ic, adls, strlen( adls ) ); + adls = xt_to_string( adl ); + msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen( adls ), adls ); g_free( adls ); } diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 75417fae..d10d7c19 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -34,31 +34,36 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c static int msn_sb_command( gpointer data, char **cmd, int num_parts ); static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); -int msn_sb_write( struct msn_switchboard *sb, char *s, int len ) +int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) { + va_list params; + char *out; + size_t len; int st; + va_start( params, fmt ); + out = g_strdup_vprintf( fmt, params ); + va_end( params ); + if( getenv( "BITLBEE_DEBUG" ) ) - { - write( 2, "->SB:", 5 ); - write( 2, s, len ); - } + fprintf( stderr, "->SB%d:%s", sb->fd, out ); - st = write( sb->fd, s, len ); + len = strlen( out ); + st = write( sb->fd, out, len ); + g_free( out ); if( st != len ) { msn_sb_destroy( sb ); - return( 0 ); + return 0; } - return( 1 ); + return 1; } int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ) { struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; - char buf[1024]; /* FIXME: *CHECK* the reliability of using spare sb's! */ if( ( sb = msn_sb_spare( ic ) ) ) @@ -66,8 +71,7 @@ int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ) debug( "Trying to use a spare switchboard to message %s", m->who ); sb->who = g_strdup( m->who ); - g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, m->who ); - if( msn_sb_write( sb, buf, strlen( buf ) ) ) + if( msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, m->who ) ) { /* He/She should join the switchboard soon, let's queue the message. */ sb->msgq = g_slist_append( sb->msgq, m ); @@ -78,8 +82,7 @@ int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ) debug( "Creating a new switchboard to message %s", m->who ); /* If we reach this line, there was no spare switchboard, so let's make one. */ - g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); - if( !msn_write( ic, buf, strlen( buf ) ) ) + if( !msn_ns_write( ic, -1, "XFR %d SB\r\n", ++md->trId ) ) { g_free( m->who ); g_free( m->text ); @@ -170,7 +173,7 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) { if( sb->ready ) { - char *packet, *buf; + char *buf; int i, j; /* Build the message. Convert LF to CR-LF for normal messages. */ @@ -206,17 +209,15 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) } /* Build the final packet (MSG command + the message). */ - packet = g_strdup_printf( "MSG %d N %d\r\n%s", ++sb->trId, i, buf ); - g_free( buf ); - if( msn_sb_write( sb, packet, strlen( packet ) ) ) + if( msn_sb_write( sb, "MSG %d N %d\r\n%s", ++sb->trId, i, buf ) ) { - g_free( packet ); - return( 1 ); + g_free( buf ); + return 1; } else { - g_free( packet ); - return( 0 ); + g_free( buf ); + return 0; } } else if( sb->who ) @@ -331,7 +332,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) else g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session ); - if( msn_sb_write( sb, buf, strlen( buf ) ) ) + if( msn_sb_write( sb, "%s", buf ) ) sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb ); else debug( "Error %d while connecting to switchboard server", 2 ); @@ -351,7 +352,6 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c if( sb->msgq != NULL ) { time_t now = time( NULL ); - char buf[1024]; if( now - md->first_sb_failure > 600 ) { @@ -383,8 +383,7 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c debug( "Moved queued messages back to the main queue, " "creating a new switchboard to retry." ); - g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); - if( !msn_write( ic, buf, strlen( buf ) ) ) + if( !msn_ns_write( ic, -1, "XFR %d SB\r\n", ++md->trId ) ) return FALSE; } @@ -396,7 +395,6 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) { struct msn_switchboard *sb = data; struct im_connection *ic = sb->ic; - char buf[1024]; if( !num_parts ) { @@ -425,14 +423,9 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } if( sb->who ) - { - g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, sb->who ); - return( msn_sb_write( sb, buf, strlen( buf ) ) ); - } + return msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, sb->who ); else - { debug( "Just created a switchboard, but I don't know what to do with it." ); - } } else if( strcmp( cmd[0], "IRO" ) == 0 ) { -- cgit v1.2.3 From bae06178bbe3863b39ec307c34d2781a53472272 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 3 Sep 2010 22:24:58 +0100 Subject: Rearrange things a bit to support multiple NS connections. This is apparently needed for refreshing auth. tokens. --- protocols/msn/msn.c | 27 +++-------- protocols/msn/msn.h | 41 +++++++++-------- protocols/msn/msn_util.c | 4 +- protocols/msn/ns.c | 114 ++++++++++++++++++++++++++++------------------- protocols/msn/sb.c | 12 ++--- 5 files changed, 105 insertions(+), 93 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index f37b802e..c5c05087 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -52,7 +52,6 @@ static void msn_login( account_t *acc ) struct msn_data *md = g_new0( struct msn_data, 1 ); ic->proto_data = md; - md->fd = -1; if( strchr( acc->user, '@' ) == NULL ) { @@ -61,21 +60,14 @@ static void msn_login( account_t *acc ) return; } - imcb_log( ic, "Connecting" ); - - md->fd = proxy_connect( "messenger.hotmail.com", 1863, msn_ns_connected, ic ); - if( md->fd < 0 ) - { - imcb_error( ic, "Could not connect to server" ); - imc_logout( ic, TRUE ); - return; - } - md->ic = ic; md->away_state = msn_away_state_list; md->domaintree = g_tree_new( msn_domaintree_cmp ); - msn_connections = g_slist_append( msn_connections, ic ); + msn_connections = g_slist_prepend( msn_connections, ic ); + + imcb_log( ic, "Connecting" ); + msn_ns_connect( ic, md->ns, MSN_NS_HOST, MSN_NS_PORT ); } static void msn_logout( struct im_connection *ic ) @@ -92,15 +84,8 @@ static void msn_logout( struct im_connection *ic ) } */ - if( md->fd >= 0 ) - closesocket( md->fd ); - - if( md->handler ) - { - if( md->handler->rxq ) g_free( md->handler->rxq ); - if( md->handler->cmd_text ) g_free( md->handler->cmd_text ); - g_free( md->handler ); - } + msn_ns_close( md->ns ); + msn_ns_close( md->auth ); while( md->switchboards ) msn_sb_destroy( md->switchboards->data ); diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index dae115ef..5a195348 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -43,6 +43,9 @@ #define MSNP11_PROD_ID "PROD0101{0RM?UBW" */ +#define MSN_NS_HOST "messenger.hotmail.com" +#define MSN_NS_PORT 1863 + /* Some other version. #define MSNP11_PROD_KEY "O4BG@C7BWLYQX?5G" #define MSNP11_PROD_ID "PROD01065C%ZFN6F" @@ -79,12 +82,27 @@ typedef enum MSN_DONE_ADL = 4, } msn_flags_t; +struct msn_handler_data +{ + int fd, inpa; + int rxlen; + char *rxq; + + int msglen; + char *cmd_text; + + /* Either ic or sb */ + gpointer data; + + int (*exec_command) ( struct msn_handler_data *handler, char **cmd, int count ); + int (*exec_message) ( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int count ); +}; + struct msn_data { struct im_connection *ic; - int fd; - struct msn_handler_data *handler; + struct msn_handler_data ns[1], auth[1]; msn_flags_t flags; int trId; @@ -110,6 +128,7 @@ struct msn_switchboard { struct im_connection *ic; + /* The following two are also in the handler. TODO: Clean up. */ int fd; gint inp; struct msn_handler_data *handler; @@ -151,21 +170,6 @@ struct msn_groupadd char *group; }; -struct msn_handler_data -{ - int fd; - int rxlen; - char *rxq; - - int msglen; - char *cmd_text; - - gpointer data; - - int (*exec_command) ( gpointer data, char **cmd, int count ); - int (*exec_message) ( gpointer data, char *msg, int msglen, char **cmd, int count ); -}; - typedef enum { MSN_BUDDY_FL = 1, /* Warning: FL,AL,BL *must* be 1,2,4. */ @@ -208,7 +212,8 @@ extern GSList *msn_switchboards; /* ns.c */ int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ); -gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); +gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port ); +void msn_ns_close( struct msn_handler_data *handler ); void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ); void msn_auth_got_contact_list( struct im_connection *ic ); int msn_ns_finish_login( struct im_connection *ic ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 6a16ba17..7fa68915 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -350,7 +350,7 @@ int msn_handler( struct msn_handler_data *h ) cmd_text = g_strndup( h->rxq, i ); cmd = msn_linesplit( cmd_text ); for( count = 0; cmd[count]; count ++ ); - st = h->exec_command( h->data, cmd, count ); + st = h->exec_command( h, cmd, count ); g_free( cmd_text ); /* If the connection broke, don't continue. We don't even exist anymore. */ @@ -385,7 +385,7 @@ int msn_handler( struct msn_handler_data *h ) cmd = msn_linesplit( h->cmd_text ); for( count = 0; cmd[count]; count ++ ); - st = h->exec_message( h->data, msg, h->msglen, cmd, count ); + st = h->exec_message( h, msg, h->msglen, cmd, count ); g_free( msg ); g_free( h->cmd_text ); h->cmd_text = NULL; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 23a1951d..6260e300 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -30,9 +30,10 @@ #include "soap.h" #include "xmltree.h" +static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); -static int msn_ns_command( gpointer data, char **cmd, int num_parts ); -static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); +static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts ); +static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ); static void msn_ns_send_adl_start( struct im_connection *ic ); static void msn_ns_send_adl( struct im_connection *ic ); @@ -50,7 +51,7 @@ int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) va_end( params ); if( fd < 0 ) - fd = md->fd; + fd = md->ns->fd; if( getenv( "BITLBEE_DEBUG" ) ) fprintf( stderr, "->NS%d:%s", fd, out ); @@ -68,56 +69,79 @@ int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) return 1; } -gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) +gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port ) { - struct im_connection *ic = data; - struct msn_data *md; - - if( !g_slist_find( msn_connections, ic ) ) - return FALSE; + if( handler->fd >= 0 ) + closesocket( handler->fd ); - if( source == -1 ) + handler->exec_command = msn_ns_command; + handler->exec_message = msn_ns_message; + handler->data = ic; + handler->fd = proxy_connect( host, port, msn_ns_connected, handler ); + if( handler->fd < 0 ) { imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return FALSE; } + return TRUE; +} + +static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) +{ + struct msn_handler_data *handler = data; + struct im_connection *ic = handler->data; + struct msn_data *md; + + if( !g_slist_find( msn_connections, ic ) ) + return FALSE; + md = ic->proto_data; - if( !md->handler ) - { - md->handler = g_new0( struct msn_handler_data, 1 ); - md->handler->data = ic; - md->handler->exec_command = msn_ns_command; - md->handler->exec_message = msn_ns_message; - } - else + if( source == -1 ) { - if( md->handler->rxq ) - g_free( md->handler->rxq ); - - md->handler->rxlen = 0; + imcb_error( ic, "Could not connect to server" ); + imc_logout( ic, TRUE ); + return FALSE; } - md->handler->fd = md->fd; - md->handler->rxq = g_new0( char, 1 ); + g_free( handler->rxq ); + handler->rxlen = 0; + handler->rxq = g_new0( char, 1 ); if( msn_ns_write( ic, -1, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) { - ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); + handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler ); imcb_log( ic, "Connected to server, waiting for reply" ); } return FALSE; } +void msn_ns_close( struct msn_handler_data *handler ) +{ + if( handler->fd >= 0 ) + { + closesocket( handler->fd ); + b_event_remove( handler->inpa ); + } + + handler->fd = handler->inpa = -1; + g_free( handler->rxq ); + g_free( handler->cmd_text ); + + handler->rxlen = 0; + handler->rxq = NULL; + handler->cmd_text = NULL; +} + static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ) { - struct im_connection *ic = data; - struct msn_data *md = ic->proto_data; + struct msn_handler_data *handler = data; + struct im_connection *ic = handler->data; - if( msn_handler( md->handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ + if( msn_handler( handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ { imcb_error( ic, "Error while reading from server" ); imc_logout( ic, TRUE ); @@ -128,9 +152,9 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c return TRUE; } -static int msn_ns_command( gpointer data, char **cmd, int num_parts ) +static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts ) { - struct im_connection *ic = data; + struct im_connection *ic = handler->data; struct msn_data *md = ic->proto_data; if( num_parts == 0 ) @@ -163,9 +187,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 ) { - b_event_remove( ic->inpa ); - ic->inpa = 0; - closesocket( md->fd ); + b_event_remove( handler->inpa ); + handler->inpa = -1; server = strchr( cmd[3], ':' ); if( !server ) @@ -179,8 +202,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = cmd[3]; imcb_log( ic, "Transferring to other server" ); - - md->fd = proxy_connect( server, port, msn_ns_connected, ic ); + return msn_ns_connect( ic, handler, server, port ); } else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 ) { @@ -272,9 +294,9 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } - md->handler->msglen = atoi( cmd[3] ); + handler->msglen = atoi( cmd[3] ); - if( md->handler->msglen <= 0 ) + if( handler->msglen <= 0 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); @@ -295,7 +317,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( num_parts >= 3 ) { - md->handler->msglen = atoi( cmd[2] ); + handler->msglen = atoi( cmd[2] ); } } else if( strcmp( cmd[0], "PRP" ) == 0 ) @@ -459,9 +481,9 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { imcb_error( ic, "Received IPG command, we don't handle them yet." ); - md->handler->msglen = atoi( cmd[1] ); + handler->msglen = atoi( cmd[1] ); - if( md->handler->msglen <= 0 ) + if( handler->msglen <= 0 ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); @@ -518,20 +540,20 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { /* Coming up is cmd[2] bytes of stuff we're supposed to censore. Meh. */ - md->handler->msglen = atoi( cmd[2] ); + handler->msglen = atoi( cmd[2] ); } else if( strcmp( cmd[0], "UBX" ) == 0 ) { /* Status message. */ if( num_parts >= 4 ) - md->handler->msglen = atoi( cmd[3] ); + handler->msglen = atoi( cmd[3] ); } else if( strcmp( cmd[0], "NOT" ) == 0 ) { /* Some kind of notification, poorly documented but apparently used to announce address book changes. */ if( num_parts >= 2 ) - md->handler->msglen = atoi( cmd[1] ); + handler->msglen = atoi( cmd[1] ); } else if( isdigit( cmd[0][0] ) ) { @@ -548,7 +570,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) /* Oh yes, errors can have payloads too now. Discard them for now. */ if( num_parts >= 3 ) - md->handler->msglen = atoi( cmd[2] ); + handler->msglen = atoi( cmd[2] ); } else { @@ -558,9 +580,9 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 1 ); } -static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ) +static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ) { - struct im_connection *ic = data; + struct im_connection *ic = handler->data; char *body; int blen = 0; diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index d10d7c19..898fb34f 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -31,8 +31,8 @@ #include "invitation.h" static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ); -static int msn_sb_command( gpointer data, char **cmd, int num_parts ); -static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); +static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num_parts ); +static int msn_sb_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ); int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) { @@ -391,9 +391,9 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c return FALSE; } -static int msn_sb_command( gpointer data, char **cmd, int num_parts ) +static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num_parts ) { - struct msn_switchboard *sb = data; + struct msn_switchboard *sb = handler->data; struct im_connection *ic = sb->ic; if( !num_parts ) @@ -664,9 +664,9 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) return( 1 ); } -static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ) +static int msn_sb_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ) { - struct msn_switchboard *sb = data; + struct msn_switchboard *sb = handler->data; struct im_connection *ic = sb->ic; char *body; int blen = 0; -- cgit v1.2.3 From 4aa8a046968bff0a08dc5ae96e228861fa21fcbe Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 4 Sep 2010 16:54:52 +0100 Subject: This works (includes some token sabotage code to ease testing), but I just realised there's probably no need for the additional temporary NS connection. --- protocols/msn/msn.c | 7 +++++-- protocols/msn/msn.h | 4 ++-- protocols/msn/ns.c | 15 +++++++++++---- protocols/msn/soap.c | 40 +++++++++++++++++++++++++++++++++++----- protocols/msn/soap.h | 2 +- 5 files changed, 54 insertions(+), 14 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index c5c05087..1467f033 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -63,6 +63,7 @@ static void msn_login( account_t *acc ) md->ic = ic; md->away_state = msn_away_state_list; md->domaintree = g_tree_new( msn_domaintree_cmp ); + md->ns->fd = md->auth->fd = -1; msn_connections = g_slist_prepend( msn_connections, ic ); @@ -179,6 +180,8 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) char *uux; struct msn_data *md = ic->proto_data; + strcpy( md->tokens[1], md->tokens[2] ); + if( state == NULL ) md->away_state = msn_away_state_list; else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL ) @@ -280,7 +283,7 @@ static void msn_add_permit( struct im_connection *ic, char *who ) static void msn_rem_permit( struct im_connection *ic, char *who ) { - msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL ); + //msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL ); } static void msn_add_deny( struct im_connection *ic, char *who ) @@ -298,7 +301,7 @@ static void msn_add_deny( struct im_connection *ic, char *who ) static void msn_rem_deny( struct im_connection *ic, char *who ) { - msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL ); + //msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL ); } static int msn_send_typing( struct im_connection *ic, char *who, int typing ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 5a195348..3def01a4 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -107,9 +107,9 @@ struct msn_data int trId; char *tokens[4]; - char *lock_key; + char *lock_key, *pp_policy; - GSList *msgq, *grpq; + GSList *msgq, *grpq, *soapq; GSList *switchboards; int sb_failures; time_t first_sb_failure; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 6260e300..401461b2 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -110,7 +110,7 @@ static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition handler->rxlen = 0; handler->rxq = g_new0( char, 1 ); - if( msn_ns_write( ic, -1, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) + if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) { handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler ); imcb_log( ic, "Connected to server, waiting for reply" ); @@ -172,13 +172,13 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num return( 0 ); } - return( msn_ns_write( ic, -1, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", + return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", ++md->trId, ic->acc->user ) ); } else if( strcmp( cmd[0], "CVR" ) == 0 ) { /* We don't give a damn about the information we just received */ - return msn_ns_write( ic, -1, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); + return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); } else if( strcmp( cmd[0], "XFR" ) == 0 ) { @@ -271,7 +271,14 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) { - msn_soap_passport_sso_request( ic, cmd[4], cmd[5] ); + g_free( md->pp_policy ); + md->pp_policy = g_strdup( cmd[4] ); + msn_soap_passport_sso_request( ic, cmd[5] ); + if( handler == md->auth ) + { + msn_ns_close( md->auth ); + return 0; + } } else if( strcmp( cmd[2], "OK" ) == 0 ) { diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 8d276108..592dbd4f 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -136,9 +136,24 @@ static void msn_soap_handle_response( struct http_request *http_req ) if( http_req->body_size > 0 ) { struct xt_parser *parser; + struct xt_node *err; parser = xt_new( soap_req->xml_parser, soap_req ); xt_feed( parser, http_req->reply_body, http_req->body_size ); + if( http_req->status_code == 500 && + ( err = xt_find_path( parser->root, "soap:Body/soap:Fault/detail/errorcode" ) ) && + err->text_len > 0 && strcmp( err->text, "PassportAuthFail" ) == 0 ) + { + struct msn_data *md = soap_req->ic->proto_data; + + xt_free( parser ); + if( md->auth->fd == -1 ) + msn_ns_connect( soap_req->ic, md->auth, MSN_NS_HOST, MSN_NS_PORT ); + md->soapq = g_slist_prepend( md->soapq, soap_req ); + + return; + } + xt_handle( parser, NULL, -1 ); xt_free( parser ); } @@ -201,12 +216,24 @@ static void msn_soap_debug_print( const char *headers, const char *payload ) #endif } +static int msn_soapq_empty( struct im_connection *ic ) +{ + struct msn_data *md = ic->proto_data; + + while( md->soapq ) + { + msn_soap_send_request( (struct msn_soap_req_data*) md->soapq->data ); + md->soapq = g_slist_remove( md->soapq, md->soapq->data ); + } + + return MSN_SOAP_OK; +} + /* passport_sso: Authentication MSNP15+ */ struct msn_soap_passport_sso_data { - char *policy; char *nonce; char *secret; char *error; @@ -216,6 +243,7 @@ static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_r { struct msn_soap_passport_sso_data *sd = soap_req->data; struct im_connection *ic = soap_req->ic; + struct msn_data *md = ic->proto_data; if( g_str_has_suffix( ic->acc->user, "@msn.com" ) ) soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL_MSN ); @@ -223,7 +251,7 @@ static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_r soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL ); soap_req->payload = g_markup_printf_escaped( SOAP_PASSPORT_SSO_PAYLOAD, - ic->acc->user, ic->acc->pass, sd->policy ); + ic->acc->user, ic->acc->pass, md->pp_policy ); return MSN_SOAP_OK; } @@ -300,6 +328,7 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap { struct msn_soap_passport_sso_data *sd = soap_req->data; struct im_connection *ic = soap_req->ic; + struct msn_data *md = ic->proto_data; char *key1, *key2, *key3, *blurb64; int key1_len; unsigned char *padnonce, *des3res; @@ -325,6 +354,9 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap GUINT32_TO_LE( 72 ), }; + if( md->soapq ) + return msn_soapq_empty( ic ); + if( sd->secret == NULL ) { msn_auth_got_passport_token( ic, NULL, sd->error ); @@ -363,7 +395,6 @@ static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req ) { struct msn_soap_passport_sso_data *sd = soap_req->data; - g_free( sd->policy ); g_free( sd->nonce ); g_free( sd->secret ); g_free( sd->error ); @@ -371,11 +402,10 @@ static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req ) return MSN_SOAP_OK; } -int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce ) +int msn_soap_passport_sso_request( struct im_connection *ic, const char *nonce ) { struct msn_soap_passport_sso_data *sd = g_new0( struct msn_soap_passport_sso_data, 1 ); - sd->policy = g_strdup( policy ); sd->nonce = g_strdup( nonce ); return msn_soap_start( ic, sd, msn_soap_passport_sso_build_request, diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 9fba5366..3a46af46 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -138,7 +138,7 @@ "" \ "" -int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce ); +int msn_soap_passport_sso_request( struct im_connection *ic, const char *nonce ); #define SOAP_OIM_SEND_URL "https://ows.messenger.msn.com/OimWS/oim.asmx" -- cgit v1.2.3 From 27053b516db4d0e648d666e6d9e36856af428775 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 4 Sep 2010 18:13:55 +0100 Subject: Finish re-authentication works. Should now work for OIMs as well. --- protocols/msn/msn.c | 10 ++++---- protocols/msn/msn.h | 3 ++- protocols/msn/ns.c | 5 ---- protocols/msn/soap.c | 67 ++++++++++++++++++++++++++++++++++------------------ protocols/msn/soap.h | 2 +- 5 files changed, 51 insertions(+), 36 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 1467f033..65bdd9a6 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -63,7 +63,7 @@ static void msn_login( account_t *acc ) md->ic = ic; md->away_state = msn_away_state_list; md->domaintree = g_tree_new( msn_domaintree_cmp ); - md->ns->fd = md->auth->fd = -1; + md->ns->fd = -1; msn_connections = g_slist_prepend( msn_connections, ic ); @@ -86,7 +86,6 @@ static void msn_logout( struct im_connection *ic ) */ msn_ns_close( md->ns ); - msn_ns_close( md->auth ); while( md->switchboards ) msn_sb_destroy( md->switchboards->data ); @@ -96,6 +95,7 @@ static void msn_logout( struct im_connection *ic ) for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ ) g_free( md->tokens[i] ); g_free( md->lock_key ); + g_free( md->pp_policy ); while( md->groups ) { @@ -180,8 +180,6 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) char *uux; struct msn_data *md = ic->proto_data; - strcpy( md->tokens[1], md->tokens[2] ); - if( state == NULL ) md->away_state = msn_away_state_list; else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL ) @@ -283,7 +281,7 @@ static void msn_add_permit( struct im_connection *ic, char *who ) static void msn_rem_permit( struct im_connection *ic, char *who ) { - //msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL ); + msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL ); } static void msn_add_deny( struct im_connection *ic, char *who ) @@ -301,7 +299,7 @@ static void msn_add_deny( struct im_connection *ic, char *who ) static void msn_rem_deny( struct im_connection *ic, char *who ) { - //msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL ); + msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL ); } static int msn_send_typing( struct im_connection *ic, char *who, int typing ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 3def01a4..829bbd4c 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -80,6 +80,7 @@ typedef enum MSN_GOT_PROFILE = 1, MSN_GOT_PROFILE_DN = 2, MSN_DONE_ADL = 4, + MSN_REAUTHING = 8, } msn_flags_t; struct msn_handler_data @@ -102,7 +103,7 @@ struct msn_data { struct im_connection *ic; - struct msn_handler_data ns[1], auth[1]; + struct msn_handler_data ns[1]; msn_flags_t flags; int trId; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 401461b2..d64a71ac 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -274,11 +274,6 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num g_free( md->pp_policy ); md->pp_policy = g_strdup( cmd[4] ); msn_soap_passport_sso_request( ic, cmd[5] ); - if( handler == md->auth ) - { - msn_ns_close( md->auth ); - return 0; - } } else if( strcmp( cmd[2], "OK" ) == 0 ) { diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 592dbd4f..2c26271b 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -47,6 +47,7 @@ typedef enum { MSN_SOAP_OK, MSN_SOAP_RETRY, + MSN_SOAP_REAUTH, MSN_SOAP_ABORT, } msn_soap_result_t; @@ -133,6 +134,8 @@ static void msn_soap_handle_response( struct http_request *http_req ) return; } + msn_soap_debug_print( http_req->reply_headers, http_req->reply_body ); + if( http_req->body_size > 0 ) { struct xt_parser *parser; @@ -142,33 +145,45 @@ static void msn_soap_handle_response( struct http_request *http_req ) xt_feed( parser, http_req->reply_body, http_req->body_size ); if( http_req->status_code == 500 && ( err = xt_find_path( parser->root, "soap:Body/soap:Fault/detail/errorcode" ) ) && - err->text_len > 0 && strcmp( err->text, "PassportAuthFail" ) == 0 ) + err->text_len > 0 ) { - struct msn_data *md = soap_req->ic->proto_data; - - xt_free( parser ); - if( md->auth->fd == -1 ) - msn_ns_connect( soap_req->ic, md->auth, MSN_NS_HOST, MSN_NS_PORT ); - md->soapq = g_slist_prepend( md->soapq, soap_req ); - - return; + if( strcmp( err->text, "PassportAuthFail" ) == 0 ) + { + xt_free( parser ); + st = MSN_SOAP_REAUTH; + goto fail; + } + /* TODO: Handle/report other errors. */ } xt_handle( parser, NULL, -1 ); xt_free( parser ); } - msn_soap_debug_print( http_req->reply_headers, http_req->reply_body ); - st = soap_req->handle_response( soap_req ); - + +fail: g_free( soap_req->url ); g_free( soap_req->action ); g_free( soap_req->payload ); soap_req->url = soap_req->action = soap_req->payload = NULL; if( st == MSN_SOAP_RETRY && --soap_req->ttl ) + { msn_soap_send_request( soap_req ); + } + else if( st == MSN_SOAP_REAUTH ) + { + struct msn_data *md = soap_req->ic->proto_data; + + if( !( md->flags & MSN_REAUTHING ) ) + { + /* Nonce shouldn't actually be touched for re-auths. */ + msn_soap_passport_sso_request( soap_req->ic, "blaataap" ); + md->flags |= MSN_REAUTHING; + } + md->soapq = g_slist_append( md->soapq, soap_req ); + } else { soap_req->free_data( soap_req ); @@ -241,7 +256,6 @@ struct msn_soap_passport_sso_data static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req ) { - struct msn_soap_passport_sso_data *sd = soap_req->data; struct im_connection *ic = soap_req->ic; struct msn_data *md = ic->proto_data; @@ -422,7 +436,7 @@ struct msn_soap_oim_send_data char *to; char *msg; int number; - int need_retry; + msn_soap_result_t need_retry; }; static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) @@ -443,28 +457,36 @@ static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req ) oim->number, oim->number, oim->msg ); g_free( display_name_b64 ); + oim->need_retry = MSN_SOAP_OK; return MSN_SOAP_OK; } -static xt_status msn_soap_oim_send_challenge( struct xt_node *node, gpointer data ) +static xt_status msn_soap_oim_reauth( struct xt_node *node, gpointer data ) { struct msn_soap_req_data *soap_req = data; struct msn_soap_oim_send_data *oim = soap_req->data; struct im_connection *ic = soap_req->ic; struct msn_data *md = ic->proto_data; + struct xt_node *c; - g_free( md->lock_key ); - md->lock_key = msn_p11_challenge( node->text ); - - oim->need_retry = 1; + if( ( c = xt_find_node( node->children, "LockKeyChallenge" ) ) && c->text_len > 0 ) + { + g_free( md->lock_key ); + md->lock_key = msn_p11_challenge( c->text ); + oim->need_retry = MSN_SOAP_RETRY; + } + if( xt_find_node( node->children, "RequiredAuthPolicy" ) ) + { + oim->need_retry = MSN_SOAP_REAUTH; + } return XT_HANDLED; } static const struct xt_handler_entry msn_soap_oim_send_parser[] = { - { "LockKeyChallenge", "detail", msn_soap_oim_send_challenge }, - { NULL, NULL, NULL } + { "detail", "soap:Fault", msn_soap_oim_reauth }, + { NULL, NULL, NULL } }; static int msn_soap_oim_handle_response( struct msn_soap_req_data *soap_req ) @@ -473,8 +495,7 @@ static int msn_soap_oim_handle_response( struct msn_soap_req_data *soap_req ) if( soap_req->http_req->status_code == 500 && oim->need_retry && soap_req->ttl > 0 ) { - oim->need_retry = 0; - return MSN_SOAP_RETRY; + return oim->need_retry; } else if( soap_req->http_req->status_code == 200 ) { diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 3a46af46..bd3e0245 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -125,7 +125,7 @@ "" \ "" \ "" \ - "" \ + "" \ "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" \ "" \ "" \ -- cgit v1.2.3 From 4e1be76617060e89795e381d356f81cd2cbf32dc Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 4 Sep 2010 18:23:46 +0100 Subject: Clean up any stuff stuck in the soap queue at disconnect time. --- protocols/msn/msn.c | 1 + protocols/msn/soap.c | 25 +++++++++++++++++-------- protocols/msn/soap.h | 3 +++ 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 65bdd9a6..1584efa4 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -91,6 +91,7 @@ static void msn_logout( struct im_connection *ic ) msn_sb_destroy( md->switchboards->data ); msn_msgq_purge( ic, &md->msgq ); + msn_soapq_flush( ic, FALSE ); for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ ) g_free( md->tokens[i] ); diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 2c26271b..05d91109 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -68,6 +68,7 @@ struct msn_soap_req_data }; static int msn_soap_send_request( struct msn_soap_req_data *req ); +static void msn_soap_free( struct msn_soap_req_data *soap_req ); static void msn_soap_debug_print( const char *headers, const char *payload ); static int msn_soap_start( struct im_connection *ic, @@ -126,11 +127,7 @@ static void msn_soap_handle_response( struct http_request *http_req ) if( g_slist_find( msn_connections, soap_req->ic ) == NULL ) { - soap_req->free_data( soap_req ); - g_free( soap_req->url ); - g_free( soap_req->action ); - g_free( soap_req->payload ); - g_free( soap_req ); + msn_soap_free( soap_req ); return; } @@ -231,19 +228,31 @@ static void msn_soap_debug_print( const char *headers, const char *payload ) #endif } -static int msn_soapq_empty( struct im_connection *ic ) +int msn_soapq_flush( struct im_connection *ic, gboolean resend ) { struct msn_data *md = ic->proto_data; while( md->soapq ) { - msn_soap_send_request( (struct msn_soap_req_data*) md->soapq->data ); + if( resend ) + msn_soap_send_request( (struct msn_soap_req_data*) md->soapq->data ); + else + msn_soap_free( (struct msn_soap_req_data*) md->soapq->data ); md->soapq = g_slist_remove( md->soapq, md->soapq->data ); } return MSN_SOAP_OK; } +static void msn_soap_free( struct msn_soap_req_data *soap_req ) +{ + soap_req->free_data( soap_req ); + g_free( soap_req->url ); + g_free( soap_req->action ); + g_free( soap_req->payload ); + g_free( soap_req ); +} + /* passport_sso: Authentication MSNP15+ */ @@ -369,7 +378,7 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap }; if( md->soapq ) - return msn_soapq_empty( ic ); + return msn_soapq_flush( ic, TRUE ); if( sd->secret == NULL ) { diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index bd3e0245..b13238a4 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -44,6 +44,9 @@ #include "nogaim.h" +int msn_soapq_flush( struct im_connection *ic, gboolean resend ); + + #define SOAP_HTTP_REQUEST \ "POST %s HTTP/1.0\r\n" \ "Host: %s\r\n" \ -- cgit v1.2.3 From 2c6b0f4dbc367963d21314636c4b114dc7aadd32 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 5 Sep 2010 15:09:43 +0100 Subject: Fix auth for @msn.com accounts. --- protocols/msn/soap.c | 18 +++++++++++++++++- protocols/msn/soap.h | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 05d91109..21e9feec 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -261,14 +261,21 @@ struct msn_soap_passport_sso_data char *nonce; char *secret; char *error; + char *redirect; }; static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req ) { + struct msn_soap_passport_sso_data *sd = soap_req->data; struct im_connection *ic = soap_req->ic; struct msn_data *md = ic->proto_data; - if( g_str_has_suffix( ic->acc->user, "@msn.com" ) ) + if( sd->redirect ) + { + soap_req->url = sd->redirect; + sd->redirect = NULL; + } + else if( g_str_has_suffix( ic->acc->user, "@msn.com" ) ) soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL_MSN ); else soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL ); @@ -311,9 +318,14 @@ static xt_status msn_soap_passport_failure( struct xt_node *node, gpointer data struct msn_soap_passport_sso_data *sd = soap_req->data; struct xt_node *code = xt_find_node( node->children, "faultcode" ); struct xt_node *string = xt_find_node( node->children, "faultstring" ); + struct xt_node *url; if( code == NULL || code->text_len == 0 ) sd->error = g_strdup( "Unknown error" ); + else if( strcmp( code->text, "psf:Redirect" ) == 0 && + ( url = xt_find_node( node->children, "psf:redirectUrl" ) ) && + url->text_len > 0 ) + sd->redirect = g_strdup( url->text ); else sd->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ? string->text : "no description available" ); @@ -377,6 +389,9 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap GUINT32_TO_LE( 72 ), }; + if( sd->redirect ) + return MSN_SOAP_RETRY; + if( md->soapq ) return msn_soapq_flush( ic, TRUE ); @@ -421,6 +436,7 @@ static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req ) g_free( sd->nonce ); g_free( sd->secret ); g_free( sd->error ); + g_free( sd->redirect ); return MSN_SOAP_OK; } diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index b13238a4..f49c86c4 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -61,7 +61,7 @@ int msn_soapq_flush( struct im_connection *ic, gboolean resend ); #define SOAP_PASSPORT_SSO_URL "https://login.live.com/RST.srf" -#define SOAP_PASSPORT_SSO_URL_MSN "https://msnia.login.live.com/pp550/RST.srf" +#define SOAP_PASSPORT_SSO_URL_MSN "https://msnia.login.live.com/pp800/RST.srf" #define SOAP_PASSPORT_SSO_PAYLOAD \ " Date: Fri, 1 Oct 2010 21:21:50 -0700 Subject: Fixed possible crash bug on removing contacts while the auth cookie expired. --- protocols/msn/soap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 21e9feec..baa73718 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -969,13 +969,12 @@ int msn_soap_ab_contact_add( struct im_connection *ic, bee_user_t *bu ) static int msn_soap_ab_contact_del_build_request( struct msn_soap_req_data *soap_req ) { struct msn_data *md = soap_req->ic->proto_data; - bee_user_t *bu = soap_req->data; - struct msn_buddy_data *bd = bu->data; + const char *cid = soap_req->data; soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); soap_req->action = g_strdup( SOAP_AB_CONTACT_DEL_ACTION ); soap_req->payload = msn_soap_abservice_build( SOAP_AB_CONTACT_DEL_PAYLOAD, - "Timer", md->tokens[1], bd->cid ); + "Timer", md->tokens[1], cid ); return 1; } @@ -988,12 +987,15 @@ static int msn_soap_ab_contact_del_handle_response( struct msn_soap_req_data *so static int msn_soap_ab_contact_del_free_data( struct msn_soap_req_data *soap_req ) { + g_free( soap_req->data ); return 0; } int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ) { - return msn_soap_start( ic, bu, + struct msn_buddy_data *bd = bu->data; + + return msn_soap_start( ic, g_strdup( bd->cid ), msn_soap_ab_contact_del_build_request, NULL, msn_soap_ab_contact_del_handle_response, -- cgit v1.2.3 From ed86165b5681b7c3ed8a7b2ce8bda0dafd6fcd52 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 1 Oct 2010 21:22:57 -0700 Subject: Silence some debugging stuff that was still going to stdout. --- protocols/msn/soap.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index baa73718..63e5c638 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -633,7 +633,8 @@ static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) else if( strcmp( role, "Pending" ) == 0 ) bd->flags |= MSN_BUDDY_PL; - printf( "%p %s %d\n", bu, handle, bd->flags ); + if( getenv( "BITLBEE_DEBUG" ) ) + printf( "%p %s %d\n", bu, handle, bd->flags ); return XT_HANDLED; } @@ -779,7 +780,8 @@ static xt_status msn_soap_addressbook_group( struct xt_node *node, gpointer data md->groups = g_slist_prepend( md->groups, mg ); } - printf( "%s %s\n", id, name ); + if( getenv( "BITLBEE_DEBUG" ) ) + printf( "%s %s\n", id, name ); return XT_HANDLED; } @@ -839,7 +841,8 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da if( group_id && ( group = msn_group_by_id( ic, group_id ) ) ) imcb_add_buddy( ic, handle, group->name ); - printf( "%s %s %s %s\n", id, type, handle, display_name ); + if( getenv( "BITLBEE_DEBUG" ) ) + printf( "%s %s %s %s\n", id, type, handle, display_name ); return XT_HANDLED; } -- cgit v1.2.3 From 04cd284bce74c114fde3043c951a5c8ef9eb79ae Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 1 Oct 2010 22:19:27 -0700 Subject: Export block/allow list again. The way this is done is ugly though and needs to change. --- protocols/msn/soap.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'protocols') diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 63e5c638..a1b5be76 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -625,9 +625,15 @@ static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) bd = bu->data; if( strcmp( role, "Allow" ) == 0 ) + { bd->flags |= MSN_BUDDY_AL; + ic->permit = g_slist_prepend( ic->permit, g_strdup( handle ) ); + } else if( strcmp( role, "Block" ) == 0 ) + { bd->flags |= MSN_BUDDY_BL; + ic->deny = g_slist_prepend( ic->deny, g_strdup( handle ) ); + } else if( strcmp( role, "Reverse" ) == 0 ) bd->flags |= MSN_BUDDY_RL; else if( strcmp( role, "Pending" ) == 0 ) -- cgit v1.2.3