Mercurial > pidgin
comparison libgaim/plugins/log_reader.c @ 14999:82d1a2fc6d25
[gaim-migrate @ 17778]
SF Patch #1598994 from lexande
Fixes SF Bug #1581999
Original Description:
"The gaim 2.0.0beta5 log reader plugin uses the "Date" XML field in MSN logs, the format of which varies between locales, leading to logs being displayed on incorrect/future dates in locales that do not use the MM/DD/YYYY format. This patch fixes the plugin to use the "DateTime" field which has YYYY-MM-DD date in all locales."
I totally Warmenhovened this patch. My approach:
"I'm using the Date, Time, and DateTime fields. If I can determine that the log matches the current timezone, it'll display 100% properly in the log viewer. If it has a reasonable offset, it'll display as the original time, sort in the right place, but not have a timezone abbreviation. If the offset is bogus or I can't parse the Date or Time field, it'll display in UTC, but still sort properly. I think this is as ideal as is possible, given the data we have to work with."
You don't have to understand this. ;)
committer: Tailor Script <tailor@pidgin.im>
| author | Richard Laager <rlaager@wiktel.com> |
|---|---|
| date | Sun, 19 Nov 2006 06:54:38 +0000 |
| parents | 5025e146a876 |
| children | c6fd017c4121 |
comparison
equal
deleted
inserted
replaced
| 14998:db590283788d | 14999:82d1a2fc6d25 |
|---|---|
| 443 const char *session_id; | 443 const char *session_id; |
| 444 int last_log; | 444 int last_log; |
| 445 GString *text; | 445 GString *text; |
| 446 }; | 446 }; |
| 447 | 447 |
| 448 static time_t msn_logger_parse_timestamp(xmlnode *message) | 448 /* This function is really confusing. It makes baby rlaager cry... |
| 449 { | 449 In other news: "You lost a lot of blood but we found most of it." |
| 450 */ | |
| 451 static time_t msn_logger_parse_timestamp(xmlnode *message, struct tm **tm_out) | |
| 452 { | |
| 453 const char *datetime; | |
| 454 static struct tm tm2; | |
| 455 time_t stamp; | |
| 450 const char *date; | 456 const char *date; |
| 451 const char *time; | 457 const char *time; |
| 452 struct tm tm; | 458 int month; |
| 459 int day; | |
| 460 int year; | |
| 461 int hour; | |
| 462 int min; | |
| 463 int sec; | |
| 453 char am_pm; | 464 char am_pm; |
| 454 | 465 char *str; |
| 455 g_return_val_if_fail(message != NULL, (time_t)0); | 466 static struct tm tm; |
| 467 time_t t; | |
| 468 time_t diff; | |
| 469 | |
| 470 #ifndef G_DISABLE_CHECKS | |
| 471 if (message != NULL) | |
| 472 { | |
| 473 *tm_out = NULL; | |
| 474 | |
| 475 /* Trigger the usual warning. */ | |
| 476 g_return_val_if_fail(message != NULL, (time_t)0); | |
| 477 } | |
| 478 #endif | |
| 479 | |
| 480 datetime = xmlnode_get_attrib(message, "DateTime"); | |
| 481 if (!(datetime && *datetime)) | |
| 482 { | |
| 483 gaim_debug_error("MSN log timestamp parse", | |
| 484 "Attribute missing: %s\n", "DateTime"); | |
| 485 return (time_t)0; | |
| 486 } | |
| 487 | |
| 488 stamp = gaim_str_to_time(datetime, TRUE, &tm2, NULL, NULL); | |
| 489 #ifdef HAVE_TM_GMTOFF | |
| 490 tm2.tm_gmtoff = 0; | |
| 491 #endif | |
| 492 #ifdef HAVE_STRUCT_TM_TM_ZONE | |
| 493 /* This is used in the place of a timezone abbreviation if the | |
| 494 * offset is way off. The user should never really see it, but | |
| 495 * it's here just in case. The parens are to make it clear it's | |
| 496 * not a real timezone. */ | |
| 497 tm2.tm_zone = _("(UTC)"); | |
| 498 #endif | |
| 499 | |
| 456 | 500 |
| 457 date = xmlnode_get_attrib(message, "Date"); | 501 date = xmlnode_get_attrib(message, "Date"); |
| 458 if (!(date && *date)) { | 502 if (!(date && *date)) |
| 459 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | 503 { |
| 460 "Attribute missing: %s\n", "Date"); | 504 gaim_debug_error("MSN log timestamp parse", |
| 461 return (time_t)0; | 505 "Attribute missing: %s\n", "Date"); |
| 506 *tm_out = &tm2; | |
| 507 return stamp; | |
| 462 } | 508 } |
| 463 | 509 |
| 464 time = xmlnode_get_attrib(message, "Time"); | 510 time = xmlnode_get_attrib(message, "Time"); |
| 465 if (!(time && *time)) { | 511 if (!(time && *time)) |
| 466 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | 512 { |
| 467 "Attribute missing: %s\n", "Time"); | 513 gaim_debug_error("MSN log timestamp parse", |
| 468 return (time_t)0; | 514 "Attribute missing: %s\n", "Time"); |
| 469 } | 515 *tm_out = &tm2; |
| 470 | 516 return stamp; |
| 471 if (sscanf(date, "%u/%u/%u", &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) | 517 } |
| 472 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | 518 |
| 473 "%s parsing error\n", "Date"); | 519 if (sscanf(date, "%u/%u/%u", &month, &day, &year) != 3) |
| 474 | 520 { |
| 475 if (sscanf(time, "%u:%u:%u %c", &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &am_pm) != 4) | 521 gaim_debug_error("MSN log timestamp parse", |
| 476 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | 522 "%s parsing error\n", "Date"); |
| 477 "%s parsing error\n", "Time"); | 523 *tm_out = &tm2; |
| 478 | 524 return stamp; |
| 479 tm.tm_year -= 1900; | 525 } |
| 480 tm.tm_mon -= 1; | 526 else |
| 481 if (am_pm == 'P') { | 527 { |
| 482 tm.tm_hour += 12; | 528 if (month > 12) |
| 483 } else if (tm.tm_hour == 12) { | 529 { |
| 484 /* 12 AM = 00 hr */ | 530 int tmp = day; |
| 485 tm.tm_hour = 0; | 531 day = month; |
| 486 } | 532 month = tmp; |
| 487 /* Let the C library deal with daylight savings time. */ | 533 } |
| 488 tm.tm_isdst = -1; | 534 } |
| 489 | 535 |
| 490 return mktime(&tm); | 536 if (sscanf(time, "%u:%u:%u %c", &hour, &min, &sec, &am_pm) != 4) |
| 491 } | 537 { |
| 492 | 538 gaim_debug_error("MSN log timestamp parse", |
| 539 "%s parsing error\n", "Time"); | |
| 540 *tm_out = &tm2; | |
| 541 return stamp; | |
| 542 } | |
| 543 | |
| 544 if (am_pm == 'P') { | |
| 545 hour += 12; | |
| 546 } else if (hour == 12) { | |
| 547 /* 12 AM = 00 hr */ | |
| 548 hour = 0; | |
| 549 } | |
| 550 | |
| 551 str = g_strdup_printf("%04i-%02i-%02iT%02i:%02i:%02i", year, month, day, hour, min, sec); | |
| 552 t = gaim_str_to_time(str, TRUE, &tm, NULL, NULL); | |
| 553 | |
| 554 | |
| 555 if (stamp > t) | |
| 556 diff = stamp - t; | |
| 557 else | |
| 558 diff = t - stamp; | |
| 559 | |
| 560 if (diff > (14 * 60 * 60)) | |
| 561 { | |
| 562 if (day <= 12) | |
| 563 { | |
| 564 /* Swap day & month variables, to see if it's a non-US date. */ | |
| 565 g_free(str); | |
| 566 str = g_strdup_printf("%04i-%02i-%02iT%02i:%02i:%02i", year, month, day, hour, min, sec); | |
| 567 t = gaim_str_to_time(str, TRUE, &tm, NULL, NULL); | |
| 568 | |
| 569 if (stamp > t) | |
| 570 diff = stamp - t; | |
| 571 else | |
| 572 diff = t - stamp; | |
| 573 | |
| 574 if (diff > (14 * 60 * 60)) | |
| 575 { | |
| 576 /* We got a time, it's not impossible, but | |
| 577 * the diff is too large. Display the UTC time. */ | |
| 578 g_free(str); | |
| 579 *tm_out = &tm2; | |
| 580 return stamp; | |
| 581 } | |
| 582 else | |
| 583 { | |
| 584 /* Legal time */ | |
| 585 /* Fall out */ | |
| 586 } | |
| 587 } | |
| 588 else | |
| 589 { | |
| 590 /* We got a time, it's not impossible, but | |
| 591 * the diff is too large. Display the UTC time. */ | |
| 592 g_free(str); | |
| 593 *tm_out = &tm2; | |
| 594 return stamp; | |
| 595 } | |
| 596 } | |
| 597 | |
| 598 /* If we got here, the time is legal with a reasonable offset. | |
| 599 * Let's find out if it's in our TZ. */ | |
| 600 if (gaim_str_to_time(str, FALSE, &tm, NULL, NULL) == stamp) | |
| 601 { | |
| 602 g_free(str); | |
| 603 *tm_out = &tm; | |
| 604 return stamp; | |
| 605 } | |
| 606 g_free(str); | |
| 607 | |
| 608 /* The time isn't in our TZ, but it's reasonable. */ | |
| 609 #ifdef HAVE_STRUCT_TM_TM_ZONE | |
| 610 tm.tm_zone = " "; | |
| 611 #endif | |
| 612 *tm_out = &tm; | |
| 613 return stamp; | |
| 614 } | |
| 493 | 615 |
| 494 static GList *msn_logger_list(GaimLogType type, const char *sn, GaimAccount *account) | 616 static GList *msn_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
| 495 { | 617 { |
| 496 GList *list = NULL; | 618 GList *list = NULL; |
| 497 char *username; | 619 char *username; |
| 723 if (strcmp(session_id, old_session_id)) { | 845 if (strcmp(session_id, old_session_id)) { |
| 724 /* | 846 /* |
| 725 * The session ID differs from the last message. | 847 * The session ID differs from the last message. |
| 726 * Thus, this is the start of a new conversation. | 848 * Thus, this is the start of a new conversation. |
| 727 */ | 849 */ |
| 850 struct tm *tm; | |
| 851 time_t stamp; | |
| 728 GaimLog *log; | 852 GaimLog *log; |
| 729 | 853 |
| 730 data = g_new0(struct msn_logger_data, 1); | 854 data = g_new0(struct msn_logger_data, 1); |
| 731 data->root = root; | 855 data->root = root; |
| 732 data->message = message; | 856 data->message = message; |
| 733 data->session_id = session_id; | 857 data->session_id = session_id; |
| 734 data->text = NULL; | 858 data->text = NULL; |
| 735 data->last_log = FALSE; | 859 data->last_log = FALSE; |
| 736 | 860 |
| 737 /* XXX: Look into this later... Should we pass in a struct tm? */ | 861 stamp = msn_logger_parse_timestamp(message, &tm); |
| 738 log = gaim_log_new(GAIM_LOG_IM, sn, account, NULL, msn_logger_parse_timestamp(message), NULL); | 862 |
| 863 log = gaim_log_new(GAIM_LOG_IM, sn, account, NULL, stamp, tm); | |
| 739 log->logger = msn_logger; | 864 log->logger = msn_logger; |
| 740 log->logger_data = data; | 865 log->logger_data = data; |
| 741 | 866 |
| 742 list = g_list_append(list, log); | 867 list = g_list_append(list, log); |
| 743 } | 868 } |
| 790 xmlnode *from; | 915 xmlnode *from; |
| 791 xmlnode *to; | 916 xmlnode *to; |
| 792 enum name_guesses name_guessed = NAME_GUESS_UNKNOWN; | 917 enum name_guesses name_guessed = NAME_GUESS_UNKNOWN; |
| 793 const char *their_name; | 918 const char *their_name; |
| 794 time_t time_unix; | 919 time_t time_unix; |
| 795 struct tm *tm_new; | 920 struct tm *tm; |
| 796 char *timestamp; | 921 char *timestamp; |
| 797 char *tmp; | 922 char *tmp; |
| 798 const char *style; | 923 const char *style; |
| 799 | 924 |
| 800 new_session_id = xmlnode_get_attrib(message, "SessionID"); | 925 new_session_id = xmlnode_get_attrib(message, "SessionID"); |
| 959 else | 1084 else |
| 960 text = g_string_append(text, "A82F2F"); | 1085 text = g_string_append(text, "A82F2F"); |
| 961 text = g_string_append(text, ";\">"); | 1086 text = g_string_append(text, ";\">"); |
| 962 } | 1087 } |
| 963 | 1088 |
| 964 time_unix = msn_logger_parse_timestamp(message); | 1089 time_unix = msn_logger_parse_timestamp(message, &tm); |
| 965 tm_new = localtime(&time_unix); | |
| 966 | 1090 |
| 967 timestamp = g_strdup_printf("<font size=\"2\">(%02u:%02u:%02u)</font> ", | 1091 timestamp = g_strdup_printf("<font size=\"2\">(%02u:%02u:%02u)</font> ", |
| 968 tm_new->tm_hour, tm_new->tm_min, tm_new->tm_sec); | 1092 tm->tm_hour, tm->tm_min, tm->tm_sec); |
| 969 text = g_string_append(text, timestamp); | 1093 text = g_string_append(text, timestamp); |
| 970 g_free(timestamp); | 1094 g_free(timestamp); |
| 971 | 1095 |
| 972 if (from_name) { | 1096 if (from_name) { |
| 973 text = g_string_append(text, "<b>"); | 1097 text = g_string_append(text, "<b>"); |
