Mercurial > pidgin.yaz
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) |