void pidgin_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account) { struct log_viewer_hash_t *ht; PidginLogViewer *lv = NULL; const char *name = screenname; char *title; GdkPixbuf *prpl_icon; g_return_if_fail(account != NULL); g_return_if_fail(screenname != NULL); ht = g_new0(struct log_viewer_hash_t, 1); ht->type = type; ht->screenname = g_strdup(screenname); ht->account = account; if (log_viewers == NULL) { log_viewers = g_hash_table_new(log_viewer_hash, log_viewer_equal); } else if ((lv = g_hash_table_lookup(log_viewers, ht))) { gtk_window_present(GTK_WINDOW(lv->window)); g_free(ht->screenname); g_free(ht); return; } if (type == PURPLE_LOG_CHAT) { PurpleChat *chat; chat = purple_blist_find_chat(account, screenname); if (chat != NULL) name = purple_chat_get_name(chat); title = g_strdup_printf(_("Conversations in %s"), name); } else { PurpleBuddy *buddy; buddy = purple_find_buddy(account, screenname); if (buddy != NULL) name = purple_buddy_get_contact_alias(buddy); title = g_strdup_printf(_("Conversations with %s"), name); } prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); display_log_viewer(ht, purple_log_get_logs(type, screenname, account), title, gtk_image_new_from_pixbuf(prpl_icon), purple_log_get_total_size(type, screenname, account)); if (prpl_icon) g_object_unref(prpl_icon); g_free(title); }
static void historize(PurpleConversation *c) { PurpleAccount *account = purple_conversation_get_account(c); const char *name = purple_conversation_get_name(c); PurpleConversationType convtype; GList *logs = NULL; const char *alias = name; PurpleLogReadFlags flags; char *history; char *header; PurpleMessageFlags mflag; convtype = purple_conversation_get_type(c); if (convtype == PURPLE_CONV_TYPE_IM) { GSList *buddies; GSList *cur; FinchConv *fc = FINCH_CONV(c); if (fc->list && fc->list->next) /* We were already in the middle of a conversation. */ return; /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_ims")) return; /* Find buddies for this conversation. */ buddies = purple_find_buddies(account, name); /* If we found at least one buddy, save the first buddy's alias. */ if (buddies != NULL) alias = purple_buddy_get_contact_alias((PurpleBuddy *)buddies->data); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBlistNode *node = cur->data; if ((node != NULL) && ((purple_blist_node_get_sibling_prev(node) != NULL) || (purple_blist_node_get_sibling_next(node) != NULL))) { PurpleBlistNode *node2; alias = purple_buddy_get_contact_alias((PurpleBuddy *)node); /* We've found a buddy that matches this conversation. It's part of a * PurpleContact with more than one PurpleBuddy. Loop through the PurpleBuddies * in the contact and get all the logs. */ for (node2 = purple_blist_node_get_first_child(purple_blist_node_get_parent(node)); node2 != NULL ; node2 = purple_blist_node_get_sibling_next(node2)) { logs = g_list_concat( purple_log_get_logs(PURPLE_LOG_IM, purple_buddy_get_name((PurpleBuddy *)node2), purple_buddy_get_account((PurpleBuddy *)node2)), logs); } break; } } g_slist_free(buddies); if (logs == NULL) logs = purple_log_get_logs(PURPLE_LOG_IM, name, account); else logs = g_list_sort(logs, purple_log_compare); } else if (convtype == PURPLE_CONV_TYPE_CHAT) { /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_chats")) return; logs = purple_log_get_logs(PURPLE_LOG_CHAT, name, account); } if (logs == NULL) return; mflag = PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_DELAYED; history = purple_log_read((PurpleLog*)logs->data, &flags); header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), alias, purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time))); purple_conversation_write(c, "", header, mflag, time(NULL)); g_free(header); if (flags & PURPLE_LOG_READ_NO_NEWLINE) purple_str_strip_char(history, '\n'); purple_conversation_write(c, "", history, mflag, time(NULL)); g_free(history); purple_conversation_write(c, "", "<hr>", mflag, time(NULL)); g_list_foreach(logs, (GFunc)purple_log_free, NULL); g_list_free(logs); }
static void historize(PurpleConversation *c) { PurpleAccount *account = NULL; PurpleConversationType convtype; PidginConversation *gtkconv = NULL; GtkTextIter start; GtkIMHtmlOptions options; GList *logs = NULL, *logs_head = NULL; struct tm *log_tm = NULL, *local_tm = NULL; time_t t, log_time; double limit_time = 0.0; const char *name = NULL, *alias = NULL, *LOG_MODE = NULL; char *header = NULL, *protocol = NULL, *history = NULL; int conv_counter = 0; int limit_offset = 0; int byte_counter = 0; int check_time = 0; int log_size, overshoot; account = purple_conversation_get_account(c); name = purple_conversation_get_name(c); alias = name; LOG_MODE = purple_prefs_get_string("/purple/logging/format"); /* If logging isn't enabled, don't show any history */ if(!purple_prefs_get_bool("/purple/logging/log_ims") && !purple_prefs_get_bool("/purple/logging/log_chats")) return; /* If the user wants to show 0 logs, stop now */ if(PREF_NUMBER_VAL == 0) { return; } /* If the logging mode is html, set the output options to include no newline. * Otherwise, it's normal text, so we don't need extra lines */ if(strcasecmp(LOG_MODE, "html")==0) { options = GTK_IMHTML_NO_NEWLINE; } else { options = GTK_IMHTML_NO_COLOURS; } /* Determine whether this is an IM or a chat. In either case, if the user has that * particular log type disabled, the logs file doesnt not get specified */ convtype = purple_conversation_get_type(c); if (convtype == PURPLE_CONV_TYPE_IM && PREF_IM_VAL) { GSList *cur; GSList *buddies = NULL; /* Find buddies for this conversation. */ buddies = purple_find_buddies(account, name); /* If we found at least one buddy, save the first buddy's alias. */ if (buddies != NULL) alias = purple_buddy_get_contact_alias((PurpleBuddy *)buddies->data); for(cur = buddies; cur; cur = cur->next) { PurpleBlistNode *node = cur->data; if(node && (node->prev || node->next)) { PurpleBlistNode *node2; for(node2 = node->parent->child; node2; node2 = node2->next) { logs = g_list_concat(purple_log_get_logs(PURPLE_LOG_IM, purple_buddy_get_name((PurpleBuddy *)node2), purple_buddy_get_account((PurpleBuddy *)node2)), logs); } break; } } g_slist_free(buddies); if (logs) logs = g_list_sort(logs, purple_log_compare); else logs = purple_log_get_logs(PURPLE_LOG_IM, name, account); } else if (convtype == PURPLE_CONV_TYPE_CHAT && PREF_CHAT_VAL) { logs = purple_log_get_logs(PURPLE_LOG_CHAT, purple_conversation_get_name(c), purple_conversation_get_account(c)); } gtkconv = PIDGIN_CONVERSATION(c); /* The logs are non-existant or the user has disabled this type for log displaying. */ if (!logs) { return; } /* Keep a pointer to the head of the logs for freeing later */ logs_head = logs; /* If all time prefs are not 0, prepare to check times */ if (!(PREF_MINS_VAL == 0 && PREF_HOURS_VAL == 0 && PREF_DAYS_VAL == 0)) { check_time = 1; /* Grab current time and normalize it to UTC */ t = time(NULL); local_tm = gmtime(&t); t = mktime(local_tm); limit_time = (PREF_MINS_VAL * 60.0) + (PREF_HOURS_VAL * 60.0 * 60.0) + (PREF_DAYS_VAL * 60.0 * 60.0 * 24.0); } /* The protocol will need to be adjusted for each log for correct display, so save the current imhtml protocol_name to restore it later */ protocol = g_strdup(gtk_imhtml_get_protocol_name(GTK_IMHTML(gtkconv->imhtml))); /* Calculate time for the first log */ log_tm = gmtime(&((PurpleLog*)logs->data)->time); log_time = mktime(log_tm); /* Continue to add older logs until they run out or the conditions are no longer met */ while (logs && conv_counter < PREF_NUMBER_VAL && byte_counter < PREF_BYTES_VAL && (!check_time || difftime(t, log_time) < limit_time)) { guint flags; /* Get the current log's contents as a char* */ history = purple_log_read((PurpleLog*)logs->data, &flags); log_size = strlen(history); if (flags & PURPLE_LOG_READ_NO_NEWLINE) options |= GTK_IMHTML_NO_NEWLINE; else options &= ~GTK_IMHTML_NO_NEWLINE; /* Update the overall byte count and determine if this log exceeds the limit */ byte_counter += log_size; overshoot = byte_counter - PREF_BYTES_VAL; if (overshoot > 0) { /* Start looking at the maximum log size for a newline to break at */ limit_offset = overshoot; /* Find the next \n, or stop if the end of the log is reached */ while (history[limit_offset] && history[limit_offset] != '\n') { limit_offset++; } /* If we're at or very close to the end of the log, forget this log */ if (!history[limit_offset] || (log_size - limit_offset < 3)) { limit_offset = -1; } else { /* Start at the first character after the newline */ limit_offset++; } } conv_counter++; /* If this log won't fit at all, don't display it in the conversation */ if (limit_offset != -1) { /* Set the correct protocol_name for this log */ gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), purple_account_get_protocol_name(((PurpleLog*)logs->data)->account)); /* Prepend the contents of the log starting at the calculated offset */ gtk_text_buffer_get_iter_at_offset(GTK_IMHTML(gtkconv->imhtml)->text_buffer, &start, 0); gtk_imhtml_insert_html_at_iter(GTK_IMHTML(gtkconv->imhtml), history + limit_offset, options, &start); /* Prepend the conversation header */ if (PREF_DATES_VAL) { header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), alias, purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time))); gtk_text_buffer_get_iter_at_offset(GTK_IMHTML(gtkconv->imhtml)->text_buffer, &start, 0); gtk_imhtml_insert_html_at_iter(GTK_IMHTML(gtkconv->imhtml), header, options, &start); g_free(header); } } g_free(history); if (limit_offset > 0) { /* This log had to be chopped to fit, so stop after this one */ break; } logs = logs->next; /* Recalculate log time if we haven't run out of logs */ if (logs) { log_tm = gmtime(&((PurpleLog*)logs->data)->time); log_time = mktime(log_tm); } } gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<hr>", options); /* Restore the original protocol_name */ gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol); g_free(protocol); g_object_ref(G_OBJECT(gtkconv->imhtml)); g_idle_add(_scroll_imhtml_to_end, gtkconv->imhtml); /* Clear the allocated memory that the logs are using */ g_list_foreach(logs_head, (GFunc)purple_log_free, NULL); g_list_free(logs_head); }
void pidgin_log_show_contact(PurpleContact *contact) { struct log_viewer_hash_t *ht; PurpleBlistNode *child; PidginLogViewer *lv = NULL; GList *logs = NULL; GdkPixbuf *pixbuf; GtkWidget *image; const char *name = NULL; char *title; int total_log_size = 0; g_return_if_fail(contact != NULL); ht = g_new0(struct log_viewer_hash_t, 1); ht->type = PURPLE_LOG_IM; ht->contact = contact; if (log_viewers == NULL) { log_viewers = g_hash_table_new(log_viewer_hash, log_viewer_equal); } else if ((lv = g_hash_table_lookup(log_viewers, ht))) { gtk_window_present(GTK_WINDOW(lv->window)); g_free(ht); return; } for (child = contact->node.child ; child ; child = child->next) { if (!PURPLE_BLIST_NODE_IS_BUDDY(child)) continue; logs = g_list_concat(purple_log_get_logs(PURPLE_LOG_IM, ((PurpleBuddy *)child)->name, ((PurpleBuddy *)child)->account), logs); total_log_size += purple_log_get_total_size(PURPLE_LOG_IM, ((PurpleBuddy *)child)->name, ((PurpleBuddy *)child)->account); } logs = g_list_sort(logs, purple_log_compare); image = gtk_image_new(); pixbuf = gtk_widget_render_icon(image, PIDGIN_STOCK_STATUS_PERSON, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL), "GtkWindow"); if (pixbuf) { gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf); g_object_unref(pixbuf); } else { gtk_widget_destroy(image); image = NULL; } if (contact->alias != NULL) name = contact->alias; else if (contact->priority != NULL) name = purple_buddy_get_contact_alias(contact->priority); /* This will happen if the contact doesn't have an alias, * and none of the contact's buddies are online. * There is probably a better way to deal with this. */ if (name == NULL) { if (contact->node.child != NULL && PURPLE_BLIST_NODE_IS_BUDDY(contact->node.child)) name = purple_buddy_get_contact_alias((PurpleBuddy *) contact->node.child); if (name == NULL) name = ""; } title = g_strdup_printf(_("Conversations with %s"), name); display_log_viewer(ht, logs, title, image, total_log_size); g_free(title); }
static int try_to_append(PurpleBuddy *buddy, const char *message) { int retval = 0; /* Log file to write to */ PurpleLog *log = NULL; GList *list; list = purple_log_get_logs(PURPLE_LOG_IM, buddy->name, buddy->account); if (!list) return 0; log = g_list_first(list)->data; if (!log) { if (DEBUG) printf(INTRO "Unable to append, log list empty\n"); goto cleanup; } if (!log->logger) { if (DEBUG) printf(INTRO "Unable to append logger is NULL\n"); goto cleanup; } if (!log->logger_data) { if (DEBUG) printf(INTRO "Unable to append NULL logger_data\n"); goto cleanup; } /* We must reopen log file * This should work with txt logger and html logger. * No idea about others. This is kind of hack. * * We don't know real type of logger_data. */ PurpleLogCommonLoggerData *data = log->logger_data; if (data->file) { /* Right. This should be NULL really, type might be wrong. */ if (DEBUG) printf(INTRO "WARNING incompatible logger or logging system updated!\n"); goto cleanup; } data->file = fopen(data->path, "a"); if (!data->file) { if (DEBUG) printf(INTRO "Unable to append to existing log!\n"); goto cleanup; } const char *alias = purple_buddy_get_alias(buddy); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, alias, time(NULL), message); fclose(data->file); data->file = NULL; /* All fine */ retval = 1; cleanup: g_list_foreach(list, (GFunc)purple_log_free, NULL); g_list_free(list); return retval; }
static void historize(PurpleConversation *c) { PurpleAccount *account = purple_conversation_get_account(c); const char *name = purple_conversation_get_name(c); GList *logs = NULL; const char *alias = name; guint flags; char *history; PidginConversation *gtkconv; #if 0 /* FIXME: WebView has no options */ GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS; #endif char *header; #if 0 /* FIXME: WebView has no protocol setting */ char *protocol; #endif char *escaped_alias; const char *header_date; gtkconv = PIDGIN_CONVERSATION(c); g_return_if_fail(gtkconv != NULL); /* An IM which is the first active conversation. */ g_return_if_fail(gtkconv->convs != NULL); if (PURPLE_IS_IM_CONVERSATION(c) && !gtkconv->convs->next) { GSList *buddies; GSList *cur; /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_ims")) return; /* Find buddies for this conversation. */ buddies = purple_blist_find_buddies(account, name); /* If we found at least one buddy, save the first buddy's alias. */ if (buddies != NULL) alias = purple_buddy_get_contact_alias(PURPLE_BUDDY(buddies->data)); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBlistNode *node = cur->data; PurpleBlistNode *prev = purple_blist_node_get_sibling_prev(node); PurpleBlistNode *next = purple_blist_node_get_sibling_next(node); if ((node != NULL) && ((prev != NULL) || (next != NULL))) { PurpleBlistNode *node2; PurpleBlistNode *parent = purple_blist_node_get_parent(node); PurpleBlistNode *child = purple_blist_node_get_first_child(parent); alias = purple_buddy_get_contact_alias(PURPLE_BUDDY(node)); /* We've found a buddy that matches this conversation. It's part of a * PurpleContact with more than one PurpleBuddy. Loop through the PurpleBuddies * in the contact and get all the logs. */ for (node2 = child ; node2 != NULL ; node2 = purple_blist_node_get_sibling_next(node2)) { logs = g_list_concat(purple_log_get_logs(PURPLE_LOG_IM, purple_buddy_get_name(PURPLE_BUDDY(node2)), purple_buddy_get_account(PURPLE_BUDDY(node2))), logs); } break; } } g_slist_free(buddies); if (logs == NULL) logs = purple_log_get_logs(PURPLE_LOG_IM, name, account); else logs = g_list_sort(logs, purple_log_compare); } else if (PURPLE_IS_CHAT_CONVERSATION(c)) { /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_chats")) return; logs = purple_log_get_logs(PURPLE_LOG_CHAT, name, account); } if (logs == NULL) return; history = purple_log_read((PurpleLog*)logs->data, &flags); gtkconv = PIDGIN_CONVERSATION(c); #if 0 /* FIXME: WebView has no options */ if (flags & PURPLE_LOG_READ_NO_NEWLINE) options |= GTK_IMHTML_NO_NEWLINE; #endif #if 0 /* FIXME: WebView has no protocol setting */ protocol = g_strdup(gtk_imhtml_get_protocol_name(GTK_IMHTML(gtkconv->imhtml))); gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), purple_account_get_protocol_name(((PurpleLog*)logs->data)->account)); #endif #if 0 /* TODO WebKit: Do this properly... */ if (!pidgin_webview_is_empty(PIDGIN_WEBVIEW(gtkconv->webview))) pidgin_webview_append_html(PIDGIN_WEBVIEW(gtkconv->webview), "<BR>"); #endif escaped_alias = g_markup_escape_text(alias, -1); if (((PurpleLog *)logs->data)->tm) header_date = purple_date_format_full(((PurpleLog *)logs->data)->tm); else header_date = purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time)); header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), escaped_alias, header_date); pidgin_webview_append_html(PIDGIN_WEBVIEW(gtkconv->webview), header); g_free(header); g_free(escaped_alias); g_strchomp(history); pidgin_webview_append_html(PIDGIN_WEBVIEW(gtkconv->webview), history); g_free(history); pidgin_webview_append_html(PIDGIN_WEBVIEW(gtkconv->webview), "<hr>"); #if 0 /* FIXME: WebView has no protocol setting */ gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol); g_free(protocol); #endif g_object_ref(G_OBJECT(gtkconv->webview)); g_idle_add(_scroll_webview_to_end, gtkconv->webview); g_list_foreach(logs, (GFunc)purple_log_free, NULL); g_list_free(logs); }
static void historize(PurpleConversation *c) { PurpleAccount *account = purple_conversation_get_account(c); const char *name = purple_conversation_get_name(c); PurpleConversationType convtype; GList *logs = NULL; const char *alias = name; guint flags; char *history; PidginConversation *gtkconv; GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS; char *header; char *protocol; char *escaped_alias; const char *header_date; convtype = purple_conversation_get_type(c); gtkconv = PIDGIN_CONVERSATION(c); g_return_if_fail(gtkconv != NULL); /* An IM which is the first active conversation. */ g_return_if_fail(gtkconv->convs != NULL); if (convtype == PURPLE_CONV_TYPE_IM && !gtkconv->convs->next) { GSList *buddies; GSList *cur; /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_ims")) return; /* Find buddies for this conversation. */ buddies = purple_find_buddies(account, name); /* If we found at least one buddy, save the first buddy's alias. */ if (buddies != NULL) alias = purple_buddy_get_contact_alias((PurpleBuddy *)buddies->data); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBlistNode *node = cur->data; if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL))) { PurpleBlistNode *node2; alias = purple_buddy_get_contact_alias((PurpleBuddy *)node); /* We've found a buddy that matches this conversation. It's part of a * PurpleContact with more than one PurpleBuddy. Loop through the PurpleBuddies * in the contact and get all the logs. */ for (node2 = node->parent->child ; node2 != NULL ; node2 = node2->next) { logs = g_list_concat( purple_log_get_logs(PURPLE_LOG_IM, purple_buddy_get_name((PurpleBuddy *)node2), purple_buddy_get_account((PurpleBuddy *)node2)), logs); } break; } } g_slist_free(buddies); if (logs == NULL) logs = purple_log_get_logs(PURPLE_LOG_IM, name, account); else logs = g_list_sort(logs, purple_log_compare); } else if (convtype == PURPLE_CONV_TYPE_CHAT) { /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_chats")) return; logs = purple_log_get_logs(PURPLE_LOG_CHAT, name, account); } if (logs == NULL) return; history = purple_log_read((PurpleLog*)logs->data, &flags); gtkconv = PIDGIN_CONVERSATION(c); if (flags & PURPLE_LOG_READ_NO_NEWLINE) options |= GTK_IMHTML_NO_NEWLINE; protocol = g_strdup(gtk_imhtml_get_protocol_name(GTK_IMHTML(gtkconv->imhtml))); gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), purple_account_get_protocol_name(((PurpleLog*)logs->data)->account)); if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)))) gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", options); escaped_alias = g_markup_escape_text(alias, -1); if (((PurpleLog *)logs->data)->tm) header_date = purple_date_format_full(((PurpleLog *)logs->data)->tm); else header_date = purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time)); header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), escaped_alias, header_date); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), header, options); g_free(header); g_free(escaped_alias); g_strchomp(history); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), history, options); g_free(history); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<hr>", options); gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol); g_free(protocol); g_object_ref(G_OBJECT(gtkconv->imhtml)); g_idle_add(_scroll_imhtml_to_end, gtkconv->imhtml); g_list_foreach(logs, (GFunc)purple_log_free, NULL); g_list_free(logs); }