diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-20 17:27:23 +0000 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-20 17:27:23 +0000 |
commit | e5a8118236442d51eb202a8bdebe5866449554e4 (patch) | |
tree | cf996127a7b235db035c4c5106f6bd8547c3503a /protocols | |
parent | 21029d0fe2b7b11512d2cc67495d590e9df53f85 (diff) |
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. :-(
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/msn/Makefile | 2 | ||||
-rw-r--r-- | protocols/msn/msn.c | 2 | ||||
-rw-r--r-- | protocols/msn/msn.h | 9 | ||||
-rw-r--r-- | protocols/msn/ns.c | 2 | ||||
-rw-r--r-- | protocols/msn/sb.c | 12 | ||||
-rw-r--r-- | protocols/msn/soap.c | 216 | ||||
-rw-r--r-- | protocols/msn/soap.h | 85 |
7 files changed, 325 insertions, 3 deletions
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 <wilmer@gaast.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * 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 <ctype.h> +#include <errno.h> + +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 <wilmer@gaast.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#ifndef _WIN32 +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#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 \ +"<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ +"<soap:Header>" \ + "<From memberName=\"%s\" friendlyName=\"=?utf-8?B?%s?=\" xml:lang=\"nl-nl\" proxy=\"MSNMSGR\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\" msnpVer=\"MSNP13\" buildVer=\"8.0.0328\"/>" \ + "<To memberName=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>" \ + "<Ticket passport=\"%s\" appid=\"%s\" lockkey=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>" \ + "<Sequence xmlns=\"http://schemas.xmlsoap.org/ws/2003/03/rm\">" \ + "<Identifier xmlns=\"http://schemas.xmlsoap.org/ws/2002/07/utility\">http://messenger.msn.com</Identifier>" \ + "<MessageNumber>%d</MessageNumber>" \ + "</Sequence>" \ +"</soap:Header>" \ +"<soap:Body>" \ + "<MessageType xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">text</MessageType>" \ + "<Content xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">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" \ + "</Content>" \ +"</soap:Body>" \ +"</soap:Envelope>" + +int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg ); + +#endif /* __SOAP_H__ */ |