comparison libpurple/protocols/msn/soap2.c @ 20531:a96b5015395a

signs on!
author Ka-Hing Cheung <khc@hxbc.us>
date Mon, 01 Oct 2007 00:29:44 +0000
parents 719ce4acfcb9
children 66921a5c9ae9
comparison
equal deleted inserted replaced
20530:719ce4acfcb9 20531:a96b5015395a
53 GString *buf; 53 GString *buf;
54 gsize handled_len; 54 gsize handled_len;
55 gsize body_len; 55 gsize body_len;
56 int response_code; 56 int response_code;
57 gboolean headers_done; 57 gboolean headers_done;
58 gboolean close_when_done;
59
58 MsnSoapMessage *message; 60 MsnSoapMessage *message;
59 61
60 GQueue *queue; 62 GQueue *queue;
61 MsnSoapRequest *current_request; 63 MsnSoapRequest *current_request;
62 } MsnSoapConnection; 64 } MsnSoapConnection;
72 static void msn_soap_message_send_internal(MsnSession *session, 74 static void msn_soap_message_send_internal(MsnSession *session,
73 MsnSoapMessage *message, const char *host, const char *path, 75 MsnSoapMessage *message, const char *host, const char *path,
74 MsnSoapCallback cb, gpointer cb_data, gboolean first); 76 MsnSoapCallback cb, gpointer cb_data, gboolean first);
75 77
76 static void msn_soap_request_destroy(MsnSoapRequest *req); 78 static void msn_soap_request_destroy(MsnSoapRequest *req);
79 static void msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect);
77 80
78 81
79 static MsnSoapConnection * 82 static MsnSoapConnection *
80 msn_soap_get_connection(MsnSession *session, const char *host) 83 msn_soap_get_connection(MsnSession *session, const char *host)
81 { 84 {
161 static gboolean 164 static gboolean
162 msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response) 165 msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response)
163 { 166 {
164 xmlnode *node = response->xml; 167 xmlnode *node = response->xml;
165 168
166 if (strcmp(node->name, "Envelop") == 0 && 169 if (strcmp(node->name, "Envelope") == 0 &&
167 node->child && strcmp(node->child->name, "Header") == 0 && 170 node->child && strcmp(node->child->name, "Header") == 0 &&
168 node->child->next) { 171 node->child->next) {
169 xmlnode *body = node->child->next; 172 xmlnode *body = node->child->next;
170 173 MsnSoapRequest *request;
171 if (strcmp(body->name, "Fault")) { 174
175 if (strcmp(body->name, "Fault") == 0) {
172 xmlnode *fault = xmlnode_get_child(body, "faultcode"); 176 xmlnode *fault = xmlnode_get_child(body, "faultcode");
173 MsnSoapRequest *request;
174 177
175 if (fault != NULL) { 178 if (fault != NULL) {
176 if (strcmp(fault->data, "psf:Redirect") == 0) { 179 char *faultdata = xmlnode_get_data(fault);
180
181 if (strcmp(faultdata, "psf:Redirect") == 0) {
177 xmlnode *url = xmlnode_get_child(body, "redirectUrl"); 182 xmlnode *url = xmlnode_get_child(body, "redirectUrl");
178 183
179 if (url) { 184 if (url) {
180 msn_soap_handle_redirect(conn, url->data); 185 char *urldata = xmlnode_get_data(url);
186 msn_soap_handle_redirect(conn, urldata);
187 g_free(urldata);
181 } 188 }
182 189
190 g_free(faultdata);
183 return TRUE; 191 return TRUE;
184 } else if (strcmp(fault->data, "wsse:FailedAuthentication")) { 192 } else if (strcmp(faultdata, "wsse:FailedAuthentication") == 0) {
185 xmlnode *reason = xmlnode_get_child(body, "faultstring"); 193 xmlnode *reason = xmlnode_get_child(body, "faultstring");
186 194 char *reasondata = xmlnode_get_data(reason);
195
196 msn_soap_connection_sanitize(conn, TRUE);
187 msn_session_set_error(conn->session, MSN_ERROR_AUTH, 197 msn_session_set_error(conn->session, MSN_ERROR_AUTH,
188 reason ? reason->data : NULL); 198 reasondata);
189 199
200 g_free(reasondata);
201 g_free(faultdata);
190 return FALSE; 202 return FALSE;
191 } 203 }
204
205 g_free(faultdata);
192 } 206 }
193
194 request = conn->current_request;
195 conn->current_request = NULL;
196 conn->current_request->cb(request->message, response,
197 request->cb_data);
198 msn_soap_request_destroy(request);
199 } 207 }
208
209 request = conn->current_request;
210 conn->current_request = NULL;
211 request->cb(request->message, response,
212 request->cb_data);
213 msn_soap_request_destroy(request);
200 } 214 }
201 215
202 return TRUE; 216 return TRUE;
203 } 217 }
204 218
213 gboolean handled = FALSE; 227 gboolean handled = FALSE;
214 228
215 g_return_if_fail(cond == PURPLE_INPUT_READ); 229 g_return_if_fail(cond == PURPLE_INPUT_READ);
216 230
217 count = purple_ssl_read(conn->ssl, buf, sizeof(buf)); 231 count = purple_ssl_read(conn->ssl, buf, sizeof(buf));
232 purple_debug_info("soap", "read %d bytes\n", count);
218 if (count < 0 && errno == EAGAIN) 233 if (count < 0 && errno == EAGAIN)
219 return; 234 return;
220 else if (count <= 0) { 235 else if (count <= 0) {
236 purple_debug_info("soap", "read: %s\n", strerror(errno));
221 purple_ssl_close(conn->ssl); 237 purple_ssl_close(conn->ssl);
222 conn->ssl = NULL; 238 conn->ssl = NULL;
223 msn_soap_connection_handle_next(conn); 239 msn_soap_connection_handle_next(conn);
224 return; 240 return;
225 } 241 }
231 if (conn->buf == NULL) { 247 if (conn->buf == NULL) {
232 conn->buf = g_string_new_len(buf, count); 248 conn->buf = g_string_new_len(buf, count);
233 } else { 249 } else {
234 g_string_append_len(conn->buf, buf, count); 250 g_string_append_len(conn->buf, buf, count);
235 } 251 }
252
253 purple_debug_info("soap", "current %s\n", conn->buf->str);
236 254
237 cursor = conn->buf->str + conn->handled_len; 255 cursor = conn->buf->str + conn->handled_len;
238 256
239 if (conn->headers_done) { 257 if (conn->headers_done) {
240 if (conn->buf->len - conn->handled_len >= 258 if (conn->buf->len - conn->handled_len >=
263 conn->handled_len = linebreak - conn->buf->str + 2; 281 conn->handled_len = linebreak - conn->buf->str + 2;
264 282
265 if (conn->response_code == 0) { 283 if (conn->response_code == 0) {
266 if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) { 284 if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) {
267 /* something horribly wrong */ 285 /* something horribly wrong */
268 msn_soap_connection_handle_next(conn);
269 purple_ssl_close(conn->ssl); 286 purple_ssl_close(conn->ssl);
270 conn->ssl = NULL; 287 conn->ssl = NULL;
288 msn_soap_connection_handle_next(conn);
271 handled = TRUE; 289 handled = TRUE;
272 break; 290 break;
273 } else if (conn->response_code == 503) { 291 } else if (conn->response_code == 503) {
292 msn_soap_connection_sanitize(conn, TRUE);
274 msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL); 293 msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
275 return; 294 return;
276 } 295 }
277 } else if (cursor == linebreak) { 296 } else if (cursor == linebreak) {
278 /* blank line */ 297 /* blank line */
279 conn->headers_done = TRUE; 298 conn->headers_done = TRUE;
280 } else { 299 } else {
281 char *sep = strstr(cursor, ": "); 300 char *line = g_strndup(cursor, linebreak - cursor);
282 char *key = cursor; 301 char *sep = strstr(line, ": ");
283 char *value = sep + 2; 302 char *key = line;
284 303 char *value;
304
305 if (sep == NULL) {
306 purple_debug_info("soap", "ignoring malformed line: %s\n", line);
307 g_free(line);
308 goto loop_end;
309 }
310
311 value = sep + 2;
285 *sep = '\0'; 312 *sep = '\0';
286 *linebreak = '\0';
287 msn_soap_message_add_header(conn->message, key, value); 313 msn_soap_message_add_header(conn->message, key, value);
314 purple_debug_info("soap", "header %s: %s\n", key, value);
288 315
289 if ((conn->response_code == 301 || conn->response_code == 300) 316 if ((conn->response_code == 301 || conn->response_code == 300)
290 && strcmp(key, "Location") == 0) { 317 && strcmp(key, "Location") == 0) {
291 318
292 msn_soap_handle_redirect(conn, value); 319 msn_soap_handle_redirect(conn, value);
293 320
294 handled = TRUE; 321 handled = TRUE;
322 g_free(line);
295 break; 323 break;
296 } else if (conn->response_code == 401 && 324 } else if (conn->response_code == 401 &&
297 strcmp(key, "WWW-Authenticate") == 0) { 325 strcmp(key, "WWW-Authenticate") == 0) {
298 char *error = strstr(value, "cbtxt="); 326 char *error = strstr(value, "cbtxt=");
299 327
300 if (error) { 328 if (error) {
301 error += strlen("cbtxt="); 329 error += strlen("cbtxt=");
302 } 330 }
303 331
332 msn_soap_connection_sanitize(conn, TRUE);
304 msn_session_set_error(conn->session, MSN_ERROR_AUTH, 333 msn_session_set_error(conn->session, MSN_ERROR_AUTH,
305 error ? purple_url_decode(error) : NULL); 334 error ? purple_url_decode(error) : NULL);
306 335
336 g_free(line);
307 return; 337 return;
308 } else if (strcmp(key, "Content-Length") == 0) { 338 } else if (strcmp(key, "Content-Length") == 0) {
309 conn->body_len = atoi(value); 339 conn->body_len = atoi(value);
340 } else if (strcmp(key, "Connection") == 0) {
341 if (strcmp(value, "close") == 0) {
342 conn->close_when_done = TRUE;
343 }
310 } 344 }
311 } 345 }
346
347 loop_end:
348 cursor = conn->buf->str + conn->handled_len;
312 } 349 }
313 350
314 if (handled) { 351 if (handled) {
315 msn_soap_connection_handle_next(conn); 352 msn_soap_connection_handle_next(conn);
316 } 353 }
340 377
341 if (conn->handled_len < conn->buf->len) 378 if (conn->handled_len < conn->buf->len)
342 return; 379 return;
343 380
344 /* we are done! */ 381 /* we are done! */
382 g_string_free(conn->buf, TRUE);
383 conn->buf = NULL;
384 conn->handled_len = 0;
385 conn->body_len = 0;
386 conn->response_code = 0;
387 conn->headers_done = FALSE;
388 conn->close_when_done = FALSE;
389
345 purple_input_remove(conn->event_handle); 390 purple_input_remove(conn->event_handle);
346 conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ, 391 conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ,
347 msn_soap_read_cb, conn); 392 msn_soap_read_cb, conn);
348 } 393 }
349 394
394 } 439 }
395 440
396 g_string_append(conn->buf, "\r\n"); 441 g_string_append(conn->buf, "\r\n");
397 g_string_append(conn->buf, body); 442 g_string_append(conn->buf, body);
398 443
444 purple_debug_info("soap", "%s\n", conn->buf->str);
445
399 conn->handled_len = 0; 446 conn->handled_len = 0;
400 conn->current_request = req; 447 conn->current_request = req;
401 448
402 conn->event_handle = purple_input_add(conn->ssl->fd, 449 conn->event_handle = purple_input_add(conn->ssl->fd,
403 PURPLE_INPUT_WRITE, msn_soap_write_cb, conn); 450 PURPLE_INPUT_WRITE, msn_soap_write_cb, conn);
442 conn->event_handle = purple_timeout_add(0, msn_soap_connection_run, 489 conn->event_handle = purple_timeout_add(0, msn_soap_connection_run,
443 conn); 490 conn);
444 } 491 }
445 492
446 static void 493 static void
494 msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect)
495 {
496 if (conn->event_handle) {
497 purple_input_remove(conn->event_handle);
498 conn->event_handle = 0;
499 }
500
501 if (conn->message) {
502 msn_soap_message_destroy(conn->message);
503 conn->message = NULL;
504 }
505
506 if (conn->buf) {
507 g_string_free(conn->buf, TRUE);
508 conn->buf = NULL;
509 }
510
511 if (conn->ssl && (disconnect || conn->close_when_done)) {
512 purple_ssl_close(conn->ssl);
513 conn->ssl = NULL;
514 }
515
516 if (conn->current_request) {
517 msn_soap_request_destroy(conn->current_request);
518 conn->current_request = NULL;
519 }
520 }
521
522 static void
447 msn_soap_connection_handle_next(MsnSoapConnection *conn) 523 msn_soap_connection_handle_next(MsnSoapConnection *conn)
448 { 524 {
449 purple_input_remove(conn->event_handle); 525 msn_soap_connection_sanitize(conn, FALSE);
450 conn->event_handle = 0;
451
452 msn_soap_message_destroy(conn->message);
453 conn->message = NULL;
454 g_string_free(conn->buf, TRUE);
455 conn->buf = NULL;
456 526
457 conn->event_handle = purple_timeout_add(0, msn_soap_connection_run, conn); 527 conn->event_handle = purple_timeout_add(0, msn_soap_connection_run, conn);
458 528
459 if (conn->current_request) { 529 if (conn->current_request) {
460 MsnSoapRequest *req = conn->current_request; 530 MsnSoapRequest *req = conn->current_request;
481 MsnSoapRequest *req = conn->current_request; 551 MsnSoapRequest *req = conn->current_request;
482 conn->current_request = NULL; 552 conn->current_request = NULL;
483 msn_soap_connection_destroy_foreach_cb(req, conn); 553 msn_soap_connection_destroy_foreach_cb(req, conn);
484 } 554 }
485 555
556 msn_soap_connection_sanitize(conn, TRUE);
486 g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn); 557 g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn);
487 558 g_queue_free(conn->queue);
488 purple_input_remove(conn->event_handle); 559
489 conn->event_handle = 0;
490
491 if (conn->ssl) {
492 purple_ssl_close(conn->ssl);
493 conn->ssl = NULL;
494 }
495
496 msn_soap_message_destroy(conn->message);
497 g_string_free(conn->buf, TRUE);
498 g_free(conn->host); 560 g_free(conn->host);
499 g_queue_free(conn->queue);
500 g_free(conn); 561 g_free(conn);
501 } 562 }
502 563
503 MsnSoapMessage * 564 MsnSoapMessage *
504 msn_soap_message_new(const char *action, xmlnode *xml) 565 msn_soap_message_new(const char *action, xmlnode *xml)