Mercurial > pidgin
comparison src/protocols/msn/notification.c @ 8171:d0ba2f7b40e7
[gaim-migrate @ 8884]
Committing one of shx's MSN patches, which splits off the Nexus connection
code into nexus.[ch] and cleans it up a bit.
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Tue, 27 Jan 2004 04:46:05 +0000 |
| parents | 2c32ee9d4fe4 |
| children | f347c8d25cf5 |
comparison
equal
deleted
inserted
replaced
| 8170:9d1a984681fe | 8171:d0ba2f7b40e7 |
|---|---|
| 126 (char *)msn_user_get_name(user)); | 126 (char *)msn_user_get_name(user)); |
| 127 | 127 |
| 128 return TRUE; | 128 return TRUE; |
| 129 } | 129 } |
| 130 | 130 |
| 131 static size_t | |
| 132 msn_ssl_read(GaimSslConnection *gsc, char **dest_buffer) | |
| 133 { | |
| 134 size_t size = 0, s; | |
| 135 char *buffer = NULL; | |
| 136 char temp_buf[4096]; | |
| 137 | |
| 138 while ((s = gaim_ssl_read(gsc, temp_buf, sizeof(temp_buf))) > 0) | |
| 139 { | |
| 140 char *new_buffer = g_new(char, size + s + 1); | |
| 141 | |
| 142 if (buffer != NULL) | |
| 143 { | |
| 144 strncpy(new_buffer, buffer, size); | |
| 145 | |
| 146 g_free(buffer); | |
| 147 } | |
| 148 | |
| 149 buffer = new_buffer; | |
| 150 | |
| 151 strncpy(buffer + size, temp_buf, s); | |
| 152 | |
| 153 buffer[size + s] = '\0'; | |
| 154 | |
| 155 size += s; | |
| 156 } | |
| 157 | |
| 158 *dest_buffer = buffer; | |
| 159 | |
| 160 return size; | |
| 161 } | |
| 162 | |
| 163 /************************************************************************** | 131 /************************************************************************** |
| 164 * Callbacks | 132 * Callbacks |
| 165 **************************************************************************/ | 133 **************************************************************************/ |
| 166 static void | 134 static void |
| 167 msn_accept_add_cb(MsnPermitAdd *pa) | 135 msn_accept_add_cb(MsnPermitAdd *pa) |
| 310 5, MSN_CONNECT_STEPS); | 278 5, MSN_CONNECT_STEPS); |
| 311 | 279 |
| 312 return TRUE; | 280 return TRUE; |
| 313 } | 281 } |
| 314 | 282 |
| 315 static void | |
| 316 login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) | |
| 317 { | |
| 318 MsnServConn *servconn = (MsnServConn *)data; | |
| 319 GaimAccount *account = servconn->session->account; | |
| 320 GaimConnection *gc = gaim_account_get_connection(account); | |
| 321 | |
| 322 gaim_connection_error(gc, _("Unable to connect to server")); | |
| 323 } | |
| 324 | |
| 325 static void | |
| 326 login_connect_cb(gpointer data, GaimSslConnection *gsc, | |
| 327 GaimInputCondition cond) | |
| 328 { | |
| 329 MsnServConn *servconn = (MsnServConn *)data; | |
| 330 MsnSession *session = servconn->session; | |
| 331 GaimConnection *gc = gaim_account_get_connection(session->account); | |
| 332 char *username, *password; | |
| 333 char *request_str; | |
| 334 char *buffer = NULL; | |
| 335 char *tpf; | |
| 336 size_t s; | |
| 337 | |
| 338 username = | |
| 339 g_strdup(gaim_url_encode(gaim_account_get_username(session->account))); | |
| 340 password = | |
| 341 g_strdup(gaim_url_encode(gaim_account_get_password(session->account))); | |
| 342 | |
| 343 tpf = (char *)g_hash_table_lookup(session->ssl_challenge_data, "tpf"); | |
| 344 | |
| 345 request_str = g_strdup_printf( | |
| 346 "GET %s HTTP/1.1\r\n" | |
| 347 "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s,pwd=%s," | |
| 348 "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%s,kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" | |
| 349 "User-Agent: MSMSGS\r\n" | |
| 350 "Host: %s\r\n" | |
| 351 "Connection: Keep-Alive\r\n" | |
| 352 "Cache-Control: no-cache\r\n" | |
| 353 "\r\n", | |
| 354 session->ssl_login_path, | |
| 355 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ru"), | |
| 356 username, password, | |
| 357 (char *)g_hash_table_lookup(session->ssl_challenge_data, "lc"), | |
| 358 (char *)g_hash_table_lookup(session->ssl_challenge_data, "id"), | |
| 359 (char *)g_hash_table_lookup(session->ssl_challenge_data, "tw"), | |
| 360 (char *)g_hash_table_lookup(session->ssl_challenge_data, "fs"), | |
| 361 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ru"), | |
| 362 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ct"), | |
| 363 (char *)g_hash_table_lookup(session->ssl_challenge_data, "kpp"), | |
| 364 (char *)g_hash_table_lookup(session->ssl_challenge_data, "kv"), | |
| 365 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ver"), | |
| 366 (tpf == NULL ? "" : tpf), | |
| 367 session->ssl_login_host); | |
| 368 | |
| 369 gaim_debug(GAIM_DEBUG_MISC, "msn", "Sending: {%s}\n", request_str); | |
| 370 | |
| 371 g_free(username); | |
| 372 g_free(password); | |
| 373 | |
| 374 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0) | |
| 375 { | |
| 376 g_free(request_str); | |
| 377 gaim_connection_error(gc, _("Unable to write to MSN Nexus server.")); | |
| 378 | |
| 379 return; | |
| 380 } | |
| 381 | |
| 382 g_free(request_str); | |
| 383 | |
| 384 if ((s = msn_ssl_read(gsc, &buffer)) <= 0) | |
| 385 { | |
| 386 gaim_connection_error(gc, _("Unable to read from MSN Nexus server.")); | |
| 387 | |
| 388 if (buffer != NULL) | |
| 389 g_free(buffer); | |
| 390 | |
| 391 return; | |
| 392 } | |
| 393 | |
| 394 gaim_ssl_close(gsc); | |
| 395 | |
| 396 gaim_debug(GAIM_DEBUG_MISC, "msn", "ssl buffer: {%s}", buffer); | |
| 397 | |
| 398 if (strstr(buffer, "HTTP/1.1 302") != NULL) | |
| 399 { | |
| 400 /* Redirect. */ | |
| 401 char *location, *c; | |
| 402 | |
| 403 if ((location = strstr(buffer, "Location: ")) == NULL) | |
| 404 { | |
| 405 gaim_connection_error(gc, | |
| 406 _("MSN Nexus server returned invalid redirect information.")); | |
| 407 | |
| 408 g_free(buffer); | |
| 409 | |
| 410 return; | |
| 411 } | |
| 412 | |
| 413 location = strchr(location, ' ') + 1; | |
| 414 | |
| 415 if ((c = strchr(location, '\r')) != NULL) | |
| 416 *c = '\0'; | |
| 417 | |
| 418 /* Skip the http:// */ | |
| 419 if ((c = strchr(location, '/')) != NULL) | |
| 420 location = c + 2; | |
| 421 | |
| 422 if ((c = strchr(location, '/')) != NULL) | |
| 423 { | |
| 424 session->ssl_login_path = g_strdup(c); | |
| 425 | |
| 426 *c = '\0'; | |
| 427 } | |
| 428 | |
| 429 session->ssl_login_host = g_strdup(location); | |
| 430 | |
| 431 session->ssl_conn = gaim_ssl_connect(session->account, | |
| 432 session->ssl_login_host, | |
| 433 GAIM_SSL_DEFAULT_PORT, | |
| 434 login_connect_cb, login_error_cb, | |
| 435 servconn); | |
| 436 } | |
| 437 else if (strstr(buffer, "HTTP/1.1 401 Unauthorized") != NULL) | |
| 438 { | |
| 439 const char *error, *c; | |
| 440 char *temp; | |
| 441 | |
| 442 if ((error = strstr(buffer, "WWW-Authenticate")) != NULL) | |
| 443 { | |
| 444 if ((error = strstr(error, "cbtxt=")) != NULL) | |
| 445 { | |
| 446 error += strlen("cbtxt="); | |
| 447 | |
| 448 if ((c = strchr(error, '\n')) == NULL) | |
| 449 c = error + strlen(error); | |
| 450 | |
| 451 temp = g_strndup(error, c - error); | |
| 452 error = gaim_url_decode(temp); | |
| 453 g_free(temp); | |
| 454 } | |
| 455 } | |
| 456 | |
| 457 if (error == NULL) | |
| 458 { | |
| 459 gaim_connection_error(gc, | |
| 460 _("Unknown error when attempting to authorize with " | |
| 461 "MSN login server.")); | |
| 462 } | |
| 463 else | |
| 464 gaim_connection_error(gc, error); | |
| 465 } | |
| 466 else | |
| 467 { | |
| 468 char *base, *c; | |
| 469 char outparams[MSN_BUF_LEN]; | |
| 470 | |
| 471 g_free(session->ssl_login_host); | |
| 472 g_free(session->ssl_login_path); | |
| 473 g_hash_table_destroy(session->ssl_challenge_data); | |
| 474 | |
| 475 session->ssl_login_host = NULL; | |
| 476 session->ssl_login_path = NULL; | |
| 477 session->ssl_challenge_data = NULL; | |
| 478 | |
| 479 #if 0 | |
| 480 /* All your base are belong to us. */ | |
| 481 base = buffer; | |
| 482 | |
| 483 /* For great cookie! */ | |
| 484 while ((base = strstr(base, "Set-Cookie: ")) != NULL) | |
| 485 { | |
| 486 base += strlen("Set-Cookie: "); | |
| 487 | |
| 488 c = strchr(base, ';'); | |
| 489 | |
| 490 session->login_cookies = | |
| 491 g_list_append(session->login_cookies, | |
| 492 g_strndup(base, c - base)); | |
| 493 } | |
| 494 #endif | |
| 495 | |
| 496 if ((base = strstr(buffer, "Authentication-Info: ")) == NULL) | |
| 497 { | |
| 498 gaim_debug(GAIM_DEBUG_ERROR, "msn", | |
| 499 "Authentication information was not found. This did " | |
| 500 "not just happen, but if it did, you're screwed. " | |
| 501 "Report this.\n"); | |
| 502 | |
| 503 return; | |
| 504 } | |
| 505 | |
| 506 base = strstr(base, "from-PP='"); | |
| 507 base += strlen("from-PP='"); | |
| 508 c = strchr(base, '\''); | |
| 509 | |
| 510 session->ssl_login_params = g_strndup(base, c - base); | |
| 511 | |
| 512 g_snprintf(outparams, sizeof(outparams), | |
| 513 "TWN S %s", session->ssl_login_params); | |
| 514 | |
| 515 g_free(session->ssl_login_params); | |
| 516 session->ssl_login_params = NULL; | |
| 517 | |
| 518 if (!msn_servconn_send_command(session->notification_conn, "USR", | |
| 519 outparams)) | |
| 520 { | |
| 521 gaim_connection_error(gc, _("Unable to request USR\n")); | |
| 522 } | |
| 523 } | |
| 524 | |
| 525 g_free(buffer); | |
| 526 } | |
| 527 | |
| 528 static void | |
| 529 nexus_connect_cb(gpointer data, GaimSslConnection *gsc, | |
| 530 GaimInputCondition cond) | |
| 531 { | |
| 532 MsnServConn *servconn = (MsnServConn *)data; | |
| 533 MsnSession *session = servconn->session; | |
| 534 GaimConnection *gc = gaim_account_get_connection(session->account); | |
| 535 char *request_str; | |
| 536 char *da_login; | |
| 537 char *base, *c; | |
| 538 char *buffer = NULL; | |
| 539 size_t s; | |
| 540 | |
| 541 request_str = g_strdup_printf("GET /rdr/pprdr.asp\r\n\r\n"); | |
| 542 | |
| 543 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0) | |
| 544 { | |
| 545 g_free(request_str); | |
| 546 gaim_connection_error(gc, _("Unable to write to MSN Nexus server.")); | |
| 547 return; | |
| 548 } | |
| 549 | |
| 550 g_free(request_str); | |
| 551 | |
| 552 if (session->ssl_url != NULL) | |
| 553 { | |
| 554 g_free(session->ssl_url); | |
| 555 session->ssl_url = NULL; | |
| 556 } | |
| 557 | |
| 558 /* Get the PassportURLs line. */ | |
| 559 if ((s = msn_ssl_read(gsc, &buffer)) <= 0) | |
| 560 { | |
| 561 gaim_connection_error(gc, _("Unable to read from MSN Nexus server.")); | |
| 562 | |
| 563 if (buffer != NULL) | |
| 564 g_free(buffer); | |
| 565 | |
| 566 return; | |
| 567 } | |
| 568 | |
| 569 if ((base = strstr(buffer, "PassportURLs")) == NULL) | |
| 570 { | |
| 571 gaim_connection_error(gc, | |
| 572 _("MSN Nexus server returned invalid information.")); | |
| 573 | |
| 574 g_free(buffer); | |
| 575 | |
| 576 return; | |
| 577 } | |
| 578 | |
| 579 if ((da_login = strstr(base, "DALogin=")) != NULL) | |
| 580 { | |
| 581 if ((da_login = strchr(da_login, '=')) != NULL) | |
| 582 da_login++; | |
| 583 | |
| 584 if ((c = strchr(da_login, ',')) != NULL) | |
| 585 *c = '\0'; | |
| 586 | |
| 587 if ((c = strchr(da_login, '/')) != NULL) | |
| 588 { | |
| 589 session->ssl_login_path = g_strdup(c); | |
| 590 | |
| 591 *c = '\0'; | |
| 592 } | |
| 593 | |
| 594 session->ssl_login_host = g_strdup(da_login); | |
| 595 } | |
| 596 | |
| 597 g_free(buffer); | |
| 598 | |
| 599 gaim_ssl_close(gsc); | |
| 600 | |
| 601 /* Now begin the connection to the login server. */ | |
| 602 session->ssl_conn = gaim_ssl_connect(session->account, | |
| 603 session->ssl_login_host, | |
| 604 GAIM_SSL_DEFAULT_PORT, | |
| 605 login_connect_cb, login_error_cb, | |
| 606 servconn); | |
| 607 } | |
| 608 | |
| 609 static gboolean | 283 static gboolean |
| 610 usr_cmd(MsnServConn *servconn, const char *command, const char **params, | 284 usr_cmd(MsnServConn *servconn, const char *command, const char **params, |
| 611 size_t param_count) | 285 size_t param_count) |
| 612 { | 286 { |
| 613 MsnSession *session = servconn->session; | 287 MsnSession *session = servconn->session; |
| 641 gaim_connection_update_progress(gc, _("Retrieving buddy list"), | 315 gaim_connection_update_progress(gc, _("Retrieving buddy list"), |
| 642 7, MSN_CONNECT_STEPS); | 316 7, MSN_CONNECT_STEPS); |
| 643 } | 317 } |
| 644 else if (!g_ascii_strcasecmp(params[1], "TWN")) | 318 else if (!g_ascii_strcasecmp(params[1], "TWN")) |
| 645 { | 319 { |
| 320 char **elems, **cur, **tokens; | |
| 321 | |
| 646 /* Passport authentication */ | 322 /* Passport authentication */ |
| 647 char *challenge_data; | 323 session->nexus = msn_nexus_new(session); |
| 648 char *key, *value = NULL; | |
| 649 char *c; | |
| 650 | |
| 651 if (session->ssl_challenge_data != NULL) | |
| 652 g_hash_table_destroy(session->ssl_challenge_data); | |
| 653 | |
| 654 session->ssl_challenge_data = | |
| 655 g_hash_table_new_full(g_str_hash, g_str_equal, | |
| 656 g_free, g_free); | |
| 657 | 324 |
| 658 /* Parse the challenge data. */ | 325 /* Parse the challenge data. */ |
| 659 | 326 elems = g_strsplit(params[3], ",", 0); |
| 660 challenge_data = g_strdup(params[3]); | 327 |
| 661 | 328 for (cur = elems; *cur != NULL; cur++) |
| 662 for (c = challenge_data, key = challenge_data; *c != '\0'; c++) | 329 { |
| 663 { | 330 tokens = g_strsplit(*cur, "=", 2); |
| 664 if (*c == '=') | 331 g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]); |
| 665 { | 332 /* Don't free each of the tokens, only the array. */ |
| 666 *c = '\0'; | 333 g_free(tokens); |
| 667 | 334 } |
| 668 value = c + 1; | 335 |
| 669 } | 336 g_strfreev(elems); |
| 670 else if (*c == ',') | 337 |
| 671 { | 338 msn_nexus_connect(session->nexus); |
| 672 *c = '\0'; | |
| 673 | |
| 674 g_hash_table_insert(session->ssl_challenge_data, | |
| 675 g_strdup(key), g_strdup(value)); | |
| 676 | |
| 677 key = c + 1; | |
| 678 } | |
| 679 } | |
| 680 | |
| 681 if (key < value) | |
| 682 { | |
| 683 /* Let's not forget the last one, it doesn't end with a ',' */ | |
| 684 g_hash_table_insert(session->ssl_challenge_data, | |
| 685 g_strdup(key), g_strdup(value)); | |
| 686 } | |
| 687 | |
| 688 g_free(challenge_data); | |
| 689 | |
| 690 #if 0 | |
| 691 passport_str = g_strdup(gaim_url_decode(params[3])); | |
| 692 | |
| 693 for (c = passport_str; *c != '\0'; c++) | |
| 694 { | |
| 695 if (*c == ',') | |
| 696 *c = '&'; | |
| 697 } | |
| 698 | |
| 699 session->ssl_url = passport_str; | |
| 700 #endif | |
| 701 | |
| 702 session->ssl_conn = gaim_ssl_connect(session->account, | |
| 703 "nexus.passport.com", | |
| 704 GAIM_SSL_DEFAULT_PORT, | |
| 705 nexus_connect_cb, login_error_cb, | |
| 706 servconn); | |
| 707 | |
| 708 if (session->ssl_conn == NULL) | |
| 709 { | |
| 710 gaim_connection_error(gc, | |
| 711 _("Unable to connect to passport server")); | |
| 712 | |
| 713 return FALSE; | |
| 714 } | |
| 715 | 339 |
| 716 gaim_connection_update_progress(gc, _("Password sent"), | 340 gaim_connection_update_progress(gc, _("Password sent"), |
| 717 6, MSN_CONNECT_STEPS); | 341 6, MSN_CONNECT_STEPS); |
| 718 } | 342 } |
| 719 else if (!g_ascii_strcasecmp(params[1], "MD5")) | 343 else if (!g_ascii_strcasecmp(params[1], "MD5")) |
