comparison src/log.c @ 12737:a1e241dd50b6

[gaim-migrate @ 15082] Conversation and Logging Message Timestamp Formatting... The idea here is that we should honor the user's locale for message timestamps in the conversation window and in the logs. I've added a signal and created a plugin that allows one to override this. The plugin is named "Message Timestamp Formats". Enabling that will by default change the timestamps back to the format we had before this commit. (That is to say, it forces the old format and ignores the locale.) The plugin also has options to show dates in the timestamps "Always", "In Chats", or "For Delayed Messages" (the default behavior). This addresses all requests for 12 hour timestamps, allows people to continue with the 24 hour timestamps we have, even if their locale says differently, enables plugin authors to override the message timestamp formats in any way they choose, and addresses requests for complete dates in logs. To recap, if you don't like the format string your locale has, enabled the "Message Timestamp Formats" plugin. committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Thu, 05 Jan 2006 20:17:36 +0000
parents 4da7062a06c2
children 4152c8f14a02
comparison
equal deleted inserted replaced
12736:f49d49444c68 12737:a1e241dd50b6
483 } 483 }
484 484
485 return g_list_sort(logs, gaim_log_compare); 485 return g_list_sort(logs, gaim_log_compare);
486 } 486 }
487 487
488 /****************************************************************************
489 * LOG SUBSYSTEM ************************************************************
490 ****************************************************************************/
491
492 void *
493 gaim_log_get_handle(void)
494 {
495 static int handle;
496
497 return &handle;
498 }
499
488 void gaim_log_init(void) 500 void gaim_log_init(void)
489 { 501 {
502 void *handle = gaim_log_get_handle();
503
490 gaim_prefs_add_none("/core/logging"); 504 gaim_prefs_add_none("/core/logging");
491 gaim_prefs_add_bool("/core/logging/log_ims", FALSE); 505 gaim_prefs_add_bool("/core/logging/log_ims", FALSE);
492 gaim_prefs_add_bool("/core/logging/log_chats", FALSE); 506 gaim_prefs_add_bool("/core/logging/log_chats", FALSE);
493 gaim_prefs_add_bool("/core/logging/log_system", FALSE); 507 gaim_prefs_add_bool("/core/logging/log_system", FALSE);
494 508
495 gaim_prefs_add_string("/core/logging/format", "txt"); 509 gaim_prefs_add_string("/core/logging/format", "txt");
496 gaim_prefs_add_bool("/core/logging/include_date_timestamps", FALSE);
497 510
498 html_logger = gaim_log_logger_new("html", _("HTML"), 8, 511 html_logger = gaim_log_logger_new("html", _("HTML"), 8,
499 NULL, 512 NULL,
500 html_logger_write, 513 html_logger_write,
501 html_logger_finalize, 514 html_logger_finalize,
527 old_logger_total_size, 540 old_logger_total_size,
528 NULL, 541 NULL,
529 old_logger_get_log_sets); 542 old_logger_get_log_sets);
530 gaim_log_logger_add(old_logger); 543 gaim_log_logger_add(old_logger);
531 544
545 gaim_signal_register(handle, "log-timestamp",
546 gaim_marshal_POINTER__POINTER_POINTER,
547 gaim_value_new(GAIM_TYPE_POINTER), 2,
548 gaim_value_new(GAIM_TYPE_SUBTYPE,
549 GAIM_SUBTYPE_LOG),
550 gaim_value_new(GAIM_TYPE_POINTER));
551
532 gaim_prefs_connect_callback(NULL, "/core/logging/format", 552 gaim_prefs_connect_callback(NULL, "/core/logging/format",
533 logger_pref_cb, NULL); 553 logger_pref_cb, NULL);
534 gaim_prefs_trigger_callback("/core/logging/format"); 554 gaim_prefs_trigger_callback("/core/logging/format");
535 555
536 logsize_users = g_hash_table_new_full((GHashFunc)_gaim_logsize_user_hash, 556 logsize_users = g_hash_table_new_full((GHashFunc)_gaim_logsize_user_hash,
537 (GEqualFunc)_gaim_logsize_user_equal, 557 (GEqualFunc)_gaim_logsize_user_equal,
538 (GDestroyNotify)_gaim_logsize_user_free_key, NULL); 558 (GDestroyNotify)_gaim_logsize_user_free_key, NULL);
539 } 559 }
540 560
561 void
562 gaim_log_uninit(void)
563 {
564 gaim_signals_unregister_by_instance(gaim_log_get_handle());
565 }
566
541 /**************************************************************************** 567 /****************************************************************************
542 * LOGGERS ****************************************************************** 568 * LOGGERS ******************************************************************
543 ****************************************************************************/ 569 ****************************************************************************/
570
571 static char *log_get_timestamp(GaimLog *log, time_t when)
572 {
573 char *date;
574 struct tm tm = *(localtime(&when));
575
576 date = gaim_signal_emit_return_1(gaim_log_get_handle(),
577 "log-timestamp",
578 log, &tm);
579 if (date == NULL)
580 {
581 char buf[64];
582
583 if (log->type == GAIM_LOG_SYSTEM || time(NULL) > when + 20*60)
584 strftime(buf, sizeof(buf), "%x %X", &tm);
585 else
586 strftime(buf, sizeof(buf), "%X", &tm);
587
588 date = g_strdup(buf);
589 }
590
591 return date;
592 }
544 593
545 void gaim_log_common_writer(GaimLog *log, const char *ext) 594 void gaim_log_common_writer(GaimLog *log, const char *ext)
546 { 595 {
547 char date[64]; 596 char date[64];
548 GaimLogCommonLoggerData *data = log->logger_data; 597 GaimLogCommonLoggerData *data = log->logger_data;
762 811
763 static void xml_logger_write(GaimLog *log, 812 static void xml_logger_write(GaimLog *log,
764 GaimMessageFlags type, 813 GaimMessageFlags type,
765 const char *from, time_t time, const char *message) 814 const char *from, time_t time, const char *message)
766 { 815 {
767 char date[64]; 816 char *date;
768 char *xhtml = NULL; 817 char *xhtml = NULL;
769 818
770 if (!log->logger_data) { 819 if (!log->logger_data) {
771 /* This log is new. We could use the loggers 'new' function, but 820 /* This log is new. We could use the loggers 'new' function, but
772 * creating a new file there would result in empty files in the case 821 * creating a new file there would result in empty files in the case
773 * that you open a convo with someone, but don't say anything. 822 * that you open a convo with someone, but don't say anything.
774 */ 823 */
824 char buf[64];
775 char *dir = gaim_log_get_log_dir(log->type, log->name, log->account); 825 char *dir = gaim_log_get_log_dir(log->type, log->name, log->account);
776 FILE *file; 826 FILE *file;
777 827
778 if (dir == NULL) 828 if (dir == NULL)
779 return; 829 return;
780 830
781 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); 831 strftime(buf, sizeof(buf), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time));
782 832
783 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); 833 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR);
784 834
785 char *filename = g_build_filename(dir, date, NULL); 835 char *filename = g_build_filename(dir, buf, NULL);
786 g_free(dir); 836 g_free(dir);
787 837
788 log->logger_data = g_fopen(filename, "a"); 838 log->logger_data = g_fopen(filename, "a");
789 if (!log->logger_data) { 839 if (!log->logger_data) {
790 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); 840 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename);
793 } 843 }
794 g_free(filename); 844 g_free(filename);
795 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" 845 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n"
796 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); 846 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n");
797 847
798 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); 848 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&log->time));
799 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", 849 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n",
800 date, log->name, prpl); 850 date, log->name, prpl);
801 } 851 }
802 852
803 /* if we can't write to the file, give up before we hurt ourselves */ 853 /* if we can't write to the file, give up before we hurt ourselves */
804 if(!data->file) 854 if(!data->file)
805 return; 855 return;
806 856
807 if (gaim_prefs_get_bool("/core/logging/include_date_timestamps")) 857 date = log_get_timestamp(log, time);
808 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time));
809 else
810 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time));
811 858
812 gaim_markup_html_to_xhtml(message, &xhtml, NULL); 859 gaim_markup_html_to_xhtml(message, &xhtml, NULL);
813 if (from) 860 if (from)
814 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", 861 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n",
815 str_from_msg_type(type), 862 str_from_msg_type(type),
821 str_from_msg_type(type), 868 str_from_msg_type(type),
822 type & GAIM_MESSAGE_SEND ? "direction='sent'" : 869 type & GAIM_MESSAGE_SEND ? "direction='sent'" :
823 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", 870 type & GAIM_MESSAGE_RECV ? "direction='received'" : "",
824 date, xhtml): 871 date, xhtml):
825 fflush(log->logger_data); 872 fflush(log->logger_data);
873 g_free(date);
826 g_free(xhtml); 874 g_free(xhtml);
827 } 875 }
828 876
829 static void xml_logger_finalize(GaimLog *log) 877 static void xml_logger_finalize(GaimLog *log)
830 { 878 {
858 906
859 static void html_logger_write(GaimLog *log, GaimMessageFlags type, 907 static void html_logger_write(GaimLog *log, GaimMessageFlags type,
860 const char *from, time_t time, const char *message) 908 const char *from, time_t time, const char *message)
861 { 909 {
862 char *msg_fixed; 910 char *msg_fixed;
863 char date[64]; 911 char *date;
864 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); 912 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account));
865 GaimLogCommonLoggerData *data = log->logger_data; 913 GaimLogCommonLoggerData *data = log->logger_data;
866 914
867 if(!data) { 915 if(!data) {
916 char buf[64];
868 const char *prpl = 917 const char *prpl =
869 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); 918 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL);
870 gaim_log_common_writer(log, ".html"); 919 gaim_log_common_writer(log, ".html");
871 920
872 data = log->logger_data; 921 data = log->logger_data;
873 922
874 /* if we can't write to the file, give up before we hurt ourselves */ 923 /* if we can't write to the file, give up before we hurt ourselves */
875 if(!data->file) 924 if(!data->file)
876 return; 925 return;
877 926
878 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); 927 strftime(buf, sizeof(buf), "%c", localtime(&log->time));
879 fprintf(data->file, "<html><head>"); 928 fprintf(data->file, "<html><head>");
880 fprintf(data->file, "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">"); 929 fprintf(data->file, "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">");
881 fprintf(data->file, "<title>"); 930 fprintf(data->file, "<title>");
882 fprintf(data->file, "Conversation with %s at %s on %s (%s)", 931 fprintf(data->file, "Conversation with %s at %s on %s (%s)",
883 log->name, date, gaim_account_get_username(log->account), prpl); 932 log->name, buf, gaim_account_get_username(log->account), prpl);
884 fprintf(data->file, "</title></head><body>"); 933 fprintf(data->file, "</title></head><body>");
885 fprintf(data->file, 934 fprintf(data->file,
886 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", 935 "<h3>Conversation with %s at %s on %s (%s)</h3>\n",
887 log->name, date, gaim_account_get_username(log->account), prpl); 936 log->name, date, gaim_account_get_username(log->account), prpl);
888
889 } 937 }
890 938
891 /* if we can't write to the file, give up before we hurt ourselves */ 939 /* if we can't write to the file, give up before we hurt ourselves */
892 if(!data->file) 940 if(!data->file)
893 return; 941 return;
894 942
895 gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); 943 gaim_markup_html_to_xhtml(message, &msg_fixed, NULL);
944 date = log_get_timestamp(log, time);
896 945
897 if(log->type == GAIM_LOG_SYSTEM){ 946 if(log->type == GAIM_LOG_SYSTEM){
898 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time));
899 fprintf(data->file, "---- %s @ %s ----<br/>\n", msg_fixed, date); 947 fprintf(data->file, "---- %s @ %s ----<br/>\n", msg_fixed, date);
900 } else { 948 } else {
901 if (gaim_prefs_get_bool("/core/logging/include_date_timestamps"))
902 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time));
903 else
904 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time));
905
906 if (type & GAIM_MESSAGE_SYSTEM) 949 if (type & GAIM_MESSAGE_SYSTEM)
907 fprintf(data->file, "<font size=\"2\">(%s)</font><b> %s</b><br/>\n", date, msg_fixed); 950 fprintf(data->file, "<font size=\"2\">(%s)</font><b> %s</b><br/>\n", date, msg_fixed);
908 else if (type & GAIM_MESSAGE_WHISPER) 951 else if (type & GAIM_MESSAGE_WHISPER)
909 fprintf(data->file, "<font color=\"#6C2585\"><font size=\"2\">(%s)</font><b> %s:</b></font> %s<br/>\n", 952 fprintf(data->file, "<font color=\"#6C2585\"><font size=\"2\">(%s)</font><b> %s:</b></font> %s<br/>\n",
910 date, from, msg_fixed); 953 date, from, msg_fixed);
927 else 970 else
928 fprintf(data->file, "<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n", 971 fprintf(data->file, "<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n",
929 date, from, msg_fixed); 972 date, from, msg_fixed);
930 } 973 }
931 } 974 }
932 975 g_free(date);
933 g_free(msg_fixed); 976 g_free(msg_fixed);
934 fflush(data->file); 977 fflush(data->file);
935 } 978 }
936 979
937 static void html_logger_finalize(GaimLog *log) 980 static void html_logger_finalize(GaimLog *log)
984 1027
985 static void txt_logger_write(GaimLog *log, 1028 static void txt_logger_write(GaimLog *log,
986 GaimMessageFlags type, 1029 GaimMessageFlags type,
987 const char *from, time_t time, const char *message) 1030 const char *from, time_t time, const char *message)
988 { 1031 {
989 char date[64]; 1032 char *date;
990 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); 1033 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account));
991 GaimLogCommonLoggerData *data = log->logger_data; 1034 GaimLogCommonLoggerData *data = log->logger_data;
992 char *stripped = NULL; 1035 char *stripped = NULL;
993 1036
994 if (data == NULL) { 1037 if (data == NULL) {
995 /* This log is new. We could use the loggers 'new' function, but 1038 /* This log is new. We could use the loggers 'new' function, but
996 * creating a new file there would result in empty files in the case 1039 * creating a new file there would result in empty files in the case
997 * that you open a convo with someone, but don't say anything. 1040 * that you open a convo with someone, but don't say anything.
998 */ 1041 */
1042 char buf[64];
999 const char *prpl = 1043 const char *prpl =
1000 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); 1044 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL);
1001 gaim_log_common_writer(log, ".txt"); 1045 gaim_log_common_writer(log, ".txt");
1002 1046
1003 data = log->logger_data; 1047 data = log->logger_data;
1004 1048
1005 /* if we can't write to the file, give up before we hurt ourselves */ 1049 /* if we can't write to the file, give up before we hurt ourselves */
1006 if(!data->file) 1050 if(!data->file)
1007 return; 1051 return;
1008 1052
1009 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); 1053 strftime(buf, sizeof(buf), "%c", localtime(&log->time));
1010 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", 1054 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n",
1011 log->name, date, gaim_account_get_username(log->account), prpl); 1055 log->name, buf, gaim_account_get_username(log->account), prpl);
1012 } 1056 }
1013 1057
1014 /* if we can't write to the file, give up before we hurt ourselves */ 1058 /* if we can't write to the file, give up before we hurt ourselves */
1015 if(!data->file) 1059 if(!data->file)
1016 return; 1060 return;
1017 1061
1018 stripped = gaim_markup_strip_html(message); 1062 stripped = gaim_markup_strip_html(message);
1019 1063 date = log_get_timestamp(log, time);
1020 if(log->type == GAIM_LOG_SYSTEM){ 1064
1021 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); 1065 if(log->type == GAIM_LOG_SYSTEM){
1022 fprintf(data->file, "---- %s @ %s ----\n", stripped, date); 1066 fprintf(data->file, "---- %s @ %s ----\n", stripped, date);
1023 } else { 1067 } else {
1024 if (gaim_prefs_get_bool("/core/logging/include_date_timestamps")) 1068 if (type & GAIM_MESSAGE_SEND ||
1025 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); 1069 type & GAIM_MESSAGE_RECV) {
1070 if (type & GAIM_MESSAGE_AUTO_RESP) {
1071 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date,
1072 from, stripped);
1073 } else {
1074 if(gaim_message_meify(stripped, -1))
1075 fprintf(data->file, "(%s) ***%s %s\n", date, from,
1076 stripped);
1077 else
1078 fprintf(data->file, "(%s) %s: %s\n", date, from,
1079 stripped);
1080 }
1081 } else if (type & GAIM_MESSAGE_SYSTEM)
1082 fprintf(data->file, "(%s) %s\n", date, stripped);
1083 else if (type & GAIM_MESSAGE_NO_LOG) {
1084 /* This shouldn't happen */
1085 g_free(stripped);
1086 return;
1087 } else if (type & GAIM_MESSAGE_WHISPER)
1088 fprintf(data->file, "(%s) *%s* %s", date, from, stripped);
1026 else 1089 else
1027 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); 1090 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "",
1028 1091 from ? ":" : "", stripped);
1029 if (type & GAIM_MESSAGE_SEND || 1092 }
1030 type & GAIM_MESSAGE_RECV) { 1093 g_free(date);
1031 if (type & GAIM_MESSAGE_AUTO_RESP) { 1094 g_free(stripped);
1032 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, 1095 fflush(data->file);
1033 from, stripped);
1034 } else {
1035 if(gaim_message_meify(stripped, -1))
1036 fprintf(data->file, "(%s) ***%s %s\n", date, from,
1037 stripped);
1038 else
1039 fprintf(data->file, "(%s) %s: %s\n", date, from,
1040 stripped);
1041 }
1042 } else if (type & GAIM_MESSAGE_SYSTEM)
1043 fprintf(data->file, "(%s) %s\n", date, stripped);
1044 else if (type & GAIM_MESSAGE_NO_LOG) {
1045 /* This shouldn't happen */
1046 g_free(stripped);
1047 return;
1048 } else if (type & GAIM_MESSAGE_WHISPER)
1049 fprintf(data->file, "(%s) *%s* %s", date, from, stripped);
1050 else
1051 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "",
1052 from ? ":" : "", stripped);
1053 }
1054
1055 fflush(data->file);
1056 g_free(stripped);
1057 } 1096 }
1058 1097
1059 static void txt_logger_finalize(GaimLog *log) 1098 static void txt_logger_finalize(GaimLog *log)
1060 { 1099 {
1061 GaimLogCommonLoggerData *data = log->logger_data; 1100 GaimLogCommonLoggerData *data = log->logger_data;