source: protocols/msn/soap.c @ 7db65b7

Last change on this file since 7db65b7 was 7db65b7, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-08-09T19:04:55Z

Not working yet, but some code for fetching the membership list. Apparently
an upgrade to MSNP15 is needed. Oh well.

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/** soap.c
2 *
3 * SOAP-related functions. Some manager at Microsoft apparently thought
4 * MSNP wasn't XMLy enough so someone stepped up and changed that. This
5 * is the result.
6 *
7 * Copyright (C) 2010 Wilmer van der Gaast <wilmer@gaast.net>
8 *
9 * This program is free software; you can redistribute it and/or modify             
10 * it under the terms of the GNU General Public License version 2                   
11 * as published by the Free Software Foundation                                     
12 *                                                                                   
13 * This program is distributed in the hope that is will be useful,                 
14 * bit WITHOU ANY WARRANTY; without even the implied warranty of                   
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                   
16 * GNU General Public License for more details.                                     
17 *                                                                                   
18 * You should have received a copy of the GNU General Public License               
19 * along with this program; if not, write to the Free Software                     
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA         
21 *
22 */
23
24#include "http_client.h"
25#include "soap.h"
26#include "msn.h"
27#include "bitlbee.h"
28#include "url.h"
29#include "misc.h"
30#include "base64.h"
31#include "xmltree.h"
32#include <ctype.h>
33#include <errno.h>
34
35typedef enum
36{
37        MSN_SOAP_OK,
38        MSN_SOAP_RETRY,
39        MSN_SOAP_ABORT,
40} msn_soap_result_t;
41
42struct msn_soap_req_data;
43
44typedef int (*msn_soap_func) ( struct msn_soap_req_data * );
45
46struct msn_soap_req_data
47{
48        void *data;
49        struct im_connection *ic;
50        int ttl;
51       
52        char *url, *action, *payload;
53        struct http_request *http_req;
54       
55        const struct xt_handler_entry *xml_parser;
56        msn_soap_func build_request, handle_response, free_data;
57};
58
59static int msn_soap_send_request( struct msn_soap_req_data *req );
60
61static int msn_soap_start( struct im_connection *ic,
62                    void *data,
63                    msn_soap_func build_request,
64                    const struct xt_handler_entry *xml_parser,
65                    msn_soap_func handle_response,
66                    msn_soap_func free_data )
67{
68        struct msn_soap_req_data *req = g_new0( struct msn_soap_req_data, 1 );
69       
70        req->ic = ic;
71        req->data = data;
72        req->xml_parser = xml_parser;
73        req->build_request = build_request;
74        req->handle_response = handle_response;
75        req->free_data = free_data;
76        req->ttl = 3;
77       
78        return msn_soap_send_request( req );
79}
80
81static void msn_soap_handle_response( struct http_request *http_req );
82
83static int msn_soap_send_request( struct msn_soap_req_data *soap_req )
84{
85        struct msn_data *md = soap_req->ic->proto_data;
86        char *http_req;
87        char *pom, *s;
88        url_t url;
89       
90        soap_req->build_request( soap_req );
91       
92        pom = g_new0( char, strlen( md->passport_token ) * 3 );
93        strcpy( pom, md->passport_token + 2 );
94        if( ( s = strchr( pom, '&' ) ) )
95                *s = '\0';
96       
97        url_set( &url, soap_req->url );
98        http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host,
99                soap_req->action, pom,
100                strlen( soap_req->payload ), soap_req->payload );
101       
102        soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS,
103                http_req, msn_soap_handle_response, soap_req );
104       
105        g_free( http_req );
106       
107        return soap_req->http_req != NULL;
108}
109
110static void msn_soap_handle_response( struct http_request *http_req )
111{
112        struct msn_soap_req_data *soap_req = http_req->data;
113        int st;
114       
115        if( http_req->body_size > 0 )
116        {
117                struct xt_parser *parser;
118               
119                parser = xt_new( soap_req->xml_parser, soap_req );
120                xt_feed( parser, http_req->reply_body, http_req->body_size );
121                xt_handle( parser, NULL, -1 );
122                xt_free( parser );
123        }
124       
125        st = soap_req->handle_response( soap_req );
126       
127        g_free( soap_req->url );
128        g_free( soap_req->action );
129        g_free( soap_req->payload );
130        soap_req->url = soap_req->action = soap_req->payload = NULL;
131       
132        if( st == MSN_SOAP_RETRY && --soap_req->ttl )
133                msn_soap_send_request( soap_req );
134        else
135        {
136                soap_req->free_data( soap_req );
137                g_free( soap_req );
138        }
139}
140
141
142/* oim_send: Sending offline messages */
143
144struct msn_soap_oim_send_data
145{
146        char *to;
147        char *msg;
148        int number;
149        int need_retry;
150};
151
152static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req )
153{
154        struct msn_soap_oim_send_data *oim = soap_req->data;
155        struct im_connection *ic = soap_req->ic;
156        struct msn_data *md = ic->proto_data;
157        char *display_name_b64;
158       
159        display_name_b64 = tobase64( ic->displayname );
160       
161        soap_req->url = g_strdup( SOAP_OIM_SEND_URL );
162        soap_req->action = g_strdup( SOAP_OIM_SEND_ACTION );
163        soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD,
164                ic->acc->user, display_name_b64, oim->to, md->passport_token,
165                MSNP11_PROD_ID, md->lock_key ? md->lock_key : "",
166                oim->number, oim->number, oim->msg );
167       
168        g_free( display_name_b64 );
169       
170        return 1;
171}
172
173static xt_status msn_soap_oim_send_challenge( struct xt_node *node, gpointer data )
174{
175        struct msn_soap_req_data *soap_req = data;
176        struct msn_soap_oim_send_data *oim = soap_req->data;
177        struct im_connection *ic = soap_req->ic;
178        struct msn_data *md = ic->proto_data;
179       
180        g_free( md->lock_key );
181        md->lock_key = msn_p11_challenge( node->text );
182       
183        oim->need_retry = 1;
184       
185        return XT_HANDLED;
186}
187
188static const struct xt_handler_entry msn_soap_oim_send_parser[] = {
189        { "LockKeyChallenge", "detail", msn_soap_oim_send_challenge },
190        { NULL,               NULL,     NULL                        }
191};
192
193static int msn_soap_oim_handle_response( struct msn_soap_req_data *soap_req )
194{
195        struct msn_soap_oim_send_data *oim = soap_req->data;
196       
197        if( soap_req->http_req->status_code == 500 && oim->need_retry && soap_req->ttl > 0 )
198        {
199                oim->need_retry = 0;
200                return MSN_SOAP_RETRY;
201        }
202        else if( soap_req->http_req->status_code == 200 )
203        {
204                imcb_log( soap_req->ic, "Offline message successfully delivered to %s", oim->to );
205                return MSN_SOAP_OK;
206        }
207        else
208        {
209                imcb_log( soap_req->ic, "Failed to deliver offline message to %s:\n%s", oim->to, oim->msg );
210                return MSN_SOAP_ABORT;
211        }
212}
213
214static int msn_soap_oim_free_data( struct msn_soap_req_data *soap_req )
215{
216        struct msn_soap_oim_send_data *oim = soap_req->data;
217       
218        g_free( oim->to );
219        g_free( oim->msg );
220        g_free( oim );
221       
222        return 0;
223}
224
225int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg )
226{
227        struct msn_soap_oim_send_data *data;
228       
229        data = g_new0( struct msn_soap_oim_send_data, 1 );
230        data->to = g_strdup( to );
231        data->msg = tobase64( msg );
232        data->number = 1;
233       
234        return msn_soap_start( ic, data, msn_soap_oim_build_request,
235                                         msn_soap_oim_send_parser,
236                                         msn_soap_oim_handle_response,
237                                         msn_soap_oim_free_data );
238}
239
240int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq )
241{
242        GSList *l;
243        char *n = NULL;
244       
245        for( l = *msgq; l; l = l->next )
246        {
247                struct msn_message *m = l->data;
248               
249                if( n == NULL )
250                        n = m->who;
251                if( strcmp( n, m->who ) == 0 )
252                        msn_soap_oim_send( ic, m->who, m->text );
253        }
254       
255        while( *msgq != NULL )
256        {
257                struct msn_message *m = (*msgq)->data;
258               
259                g_free( m->who );
260                g_free( m->text );
261                g_free( m );
262               
263                *msgq = g_slist_remove( *msgq, m );
264        }
265}
266
267
268/* memlist: Fetching the membership list (NOT address book) */
269
270#if 0
271struct msn_soap_oim_send_data
272{
273        char *to;
274        char *msg;
275        int number;
276        int need_retry;
277};
278#endif
279
280static int msn_soap_memlist_build_request( struct msn_soap_req_data *soap_req )
281{
282        soap_req->url = g_strdup( SOAP_MEMLIST_URL );
283        soap_req->action = g_strdup( SOAP_MEMLIST_ACTION );
284        soap_req->payload = g_strdup( SOAP_MEMLIST_PAYLOAD );
285       
286        return 1;
287}
288
289static const struct xt_handler_entry msn_soap_memlist_parser[] = {
290        { NULL,               NULL,     NULL                        }
291};
292
293static int msn_soap_memlist_handle_response( struct msn_soap_req_data *soap_req )
294{
295        return 0;
296}
297
298static int msn_soap_memlist_free_data( struct msn_soap_req_data *soap_req )
299{
300        return 0;
301}
302
303int msn_soap_memlist_request( struct im_connection *ic )
304{
305        return msn_soap_start( ic, NULL, msn_soap_memlist_build_request,
306                                         msn_soap_memlist_parser,
307                                         msn_soap_memlist_handle_response,
308                                         msn_soap_memlist_free_data );
309}
Note: See TracBrowser for help on using the repository browser.