source: protocols/msn/soap.c @ ffb6dea

Last change on this file since ffb6dea was ffb6dea, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-03-20T21:58:04Z

Killing some memory leaks.

  • Property mode set to 100644
File size: 6.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
59struct msn_soap_oim_send_data
60{
61        char *to;
62        char *msg;
63        int number;
64        int need_retry;
65};
66
67static int msn_soap_send_request( struct msn_soap_req_data *req );
68
69static int msn_soap_start( struct im_connection *ic,
70                    void *data,
71                    msn_soap_func build_request,
72                    const struct xt_handler_entry *xml_parser,
73                    msn_soap_func handle_response,
74                    msn_soap_func free_data )
75{
76        struct msn_soap_req_data *req = g_new0( struct msn_soap_req_data, 1 );
77       
78        req->ic = ic;
79        req->data = data;
80        req->xml_parser = xml_parser;
81        req->build_request = build_request;
82        req->handle_response = handle_response;
83        req->free_data = free_data;
84        req->ttl = 3;
85       
86        return msn_soap_send_request( req );
87}
88
89static void msn_soap_handle_response( struct http_request *http_req );
90
91static int msn_soap_send_request( struct msn_soap_req_data *soap_req )
92{
93        char *http_req;
94        url_t url;
95       
96        soap_req->build_request( soap_req );
97       
98        url_set( &url, soap_req->url );
99        http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host,
100                soap_req->action, 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
141static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req )
142{
143        struct msn_soap_oim_send_data *oim = soap_req->data;
144        struct im_connection *ic = soap_req->ic;
145        struct msn_data *md = ic->proto_data;
146        char *display_name_b64;
147       
148        display_name_b64 = tobase64( ic->displayname );
149       
150        soap_req->url = g_strdup( SOAP_OIM_SEND_URL );
151        soap_req->action = g_strdup( SOAP_OIM_ACTION_URL );
152        soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD,
153                ic->acc->user, display_name_b64, oim->to, md->passport_token,
154                MSNP11_PROD_ID, md->lock_key ? : "", oim->number, oim->number, oim->msg );
155       
156        g_free( display_name_b64 );
157       
158        return 1;
159}
160
161static xt_status msn_soap_oim_send_challenge( struct xt_node *node, gpointer data )
162{
163        struct msn_soap_req_data *soap_req = data;
164        struct msn_soap_oim_send_data *oim = soap_req->data;
165        struct im_connection *ic = soap_req->ic;
166        struct msn_data *md = ic->proto_data;
167       
168        g_free( md->lock_key );
169        md->lock_key = msn_p11_challenge( node->text );
170       
171        oim->need_retry = 1;
172       
173        return XT_HANDLED;
174}
175
176static const struct xt_handler_entry msn_soap_oim_send_parser[] = {
177        { "LockKeyChallenge", "detail", msn_soap_oim_send_challenge },
178        { NULL,               NULL,     NULL                        }
179};
180
181static int msn_soap_oim_handle_response( struct msn_soap_req_data *soap_req )
182{
183        struct msn_soap_oim_send_data *oim = soap_req->data;
184       
185        if( soap_req->http_req->status_code == 500 && oim->need_retry )
186        {
187                oim->need_retry = 0;
188                return MSN_SOAP_RETRY;
189        }
190        else if( soap_req->http_req->status_code == 200 )
191                return MSN_SOAP_OK;
192        else
193                return MSN_SOAP_ABORT;
194}
195
196static int msn_soap_oim_free_data( struct msn_soap_req_data *soap_req )
197{
198        struct msn_soap_oim_send_data *oim = soap_req->data;
199       
200        g_free( oim->to );
201        g_free( oim->msg );
202        g_free( oim );
203       
204        return 0;
205}
206
207int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg )
208{
209        struct msn_soap_oim_send_data *data;
210       
211        data = g_new0( struct msn_soap_oim_send_data, 1 );
212        data->to = g_strdup( to );
213        data->msg = tobase64( msg );
214        data->number = 1;
215       
216        return msn_soap_start( ic, data, msn_soap_oim_build_request,
217                                         msn_soap_oim_send_parser,
218                                         msn_soap_oim_handle_response,
219                                         msn_soap_oim_free_data );
220}
Note: See TracBrowser for help on using the repository browser.