log_reader.c
来自「Linux下的多协议即时通讯程序源代码」· C语言 代码 · 共 2,177 行 · 第 1/4 页
C
2,177 行
if (name_guessed != NAME_GUESS_UNKNOWN) { text = g_string_append(text, "<span style=\"color: #"); if (name_guessed == NAME_GUESS_ME) text = g_string_append(text, "16569E"); else text = g_string_append(text, "A82F2F"); text = g_string_append(text, ";\">"); } time_unix = msn_logger_parse_timestamp(message, &tm); timestamp = g_strdup_printf("<font size=\"2\">(%02u:%02u:%02u)</font> ", tm->tm_hour, tm->tm_min, tm->tm_sec); text = g_string_append(text, timestamp); g_free(timestamp); if (from_name) { text = g_string_append(text, "<b>"); if (name_guessed == NAME_GUESS_ME) { if (log->account->alias) text = g_string_append(text, log->account->alias); else text = g_string_append(text, log->account->username); } else if (name_guessed == NAME_GUESS_THEM) text = g_string_append(text, their_name); else text = g_string_append(text, from_name); text = g_string_append(text, ":</b> "); } if (name_guessed != NAME_GUESS_UNKNOWN) text = g_string_append(text, "</span>"); style = xmlnode_get_attrib(text_node, "Style"); tmp = xmlnode_get_data(text_node); if (style && *style) { text = g_string_append(text, "<span style=\""); text = g_string_append(text, style); text = g_string_append(text, "\">"); text = g_string_append(text, tmp); text = g_string_append(text, "</span>\n"); } else { text = g_string_append(text, tmp); text = g_string_append(text, "\n"); } g_free(tmp); } data->text = text; return text->str;}static int msn_logger_size (PurpleLog *log){ char *text; size_t size; g_return_val_if_fail(log != NULL, 0); if (purple_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) return 0; text = msn_logger_read(log, NULL); size = strlen(text); g_free(text); return size;}static void msn_logger_finalize(PurpleLog *log){ struct msn_logger_data *data; g_return_if_fail(log != NULL); data = log->logger_data; if (data->last_log) xmlnode_free(data->root); if (data->text) g_string_free(data->text, FALSE);}/***************************************************************************** * Trillian Logger * *****************************************************************************//* The trillian logger doesn't write logs, only reads them. This is to include * Trillian logs in the log viewer transparently. */static PurpleLogLogger *trillian_logger;static void trillian_logger_finalize(PurpleLog *log);struct trillian_logger_data { char *path; /* FIXME: Change this to use PurpleStringref like log.c:old_logger_list */ int offset; int length; char *their_nickname;};static GList *trillian_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account){ GList *list = NULL; const char *logdir; PurplePlugin *plugin; PurplePluginProtocolInfo *prpl_info; char *prpl_name; const char *buddy_name; char *filename; char *path; GError *error = NULL; gchar *contents = NULL; gsize length; gchar *line; gchar *c; g_return_val_if_fail(sn != NULL, list); g_return_val_if_fail(account != NULL, list); logdir = purple_prefs_get_string("/plugins/core/log_reader/trillian/log_directory"); /* By clearing the log directory path, this logger can be (effectively) disabled. */ if (!*logdir) return list; plugin = purple_find_prpl(purple_account_get_protocol_id(account)); if (!plugin) return NULL; prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); if (!prpl_info->list_icon) return NULL; prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1); buddy_name = purple_normalize(account, sn); filename = g_strdup_printf("%s.log", buddy_name); path = g_build_filename( logdir, prpl_name, filename, NULL); purple_debug(PURPLE_DEBUG_INFO, "Trillian log list", "Reading %s\n", path); /* FIXME: There's really no need to read the entire file at once. * See src/log.c:old_logger_list for a better approach. */ if (!g_file_get_contents(path, &contents, &length, &error)) { if (error) { g_error_free(error); error = NULL; } g_free(path); path = g_build_filename( logdir, prpl_name, "Query", filename, NULL); purple_debug(PURPLE_DEBUG_INFO, "Trillian log list", "Reading %s\n", path); if (!g_file_get_contents(path, &contents, &length, &error)) { if (error) g_error_free(error); } } g_free(filename); if (contents) { struct trillian_logger_data *data = NULL; int offset = 0; int last_line_offset = 0; line = contents; c = contents; while (*c) { offset++; if (*c != '\n') { c++; continue; } *c = '\0'; if (purple_str_has_prefix(line, "Session Close ")) { if (data && !data->length) { if (!(data->length = last_line_offset - data->offset)) { /* This log had no data, so we remove it. */ GList *last = g_list_last(list); purple_debug(PURPLE_DEBUG_INFO, "Trillian log list", "Empty log. Offset %i\n", data->offset); trillian_logger_finalize((PurpleLog *)last->data); list = g_list_delete_link(list, last); } } } else if (line[0] && line[1] && line [3] && purple_str_has_prefix(&line[3], "sion Start ")) { char *their_nickname = line; char *timestamp; if (data && !data->length) data->length = last_line_offset - data->offset; while (*their_nickname && (*their_nickname != ':')) their_nickname++; their_nickname++; /* This code actually has nothing to do with * the timestamp YET. I'm simply using this * variable for now to NUL-terminate the * their_nickname string. */ timestamp = their_nickname; while (*timestamp && *timestamp != ')') timestamp++; if (*timestamp == ')') { char *month; struct tm tm; *timestamp = '\0'; if (line[0] && line[1] && line[2]) timestamp += 3; /* Now we start dealing with the timestamp. */ /* Skip over the day name. */ while (*timestamp && (*timestamp != ' ')) timestamp++; *timestamp = '\0'; timestamp++; /* Parse out the month. */ month = timestamp; while (*timestamp && (*timestamp != ' ')) timestamp++; *timestamp = '\0'; timestamp++; /* Parse the day, time, and year. */ if (sscanf(timestamp, "%u %u:%u:%u %u", &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tm.tm_year) != 5) { purple_debug(PURPLE_DEBUG_ERROR, "Trillian log timestamp parse", "Session Start parsing error\n"); } else { PurpleLog *log; tm.tm_year -= 1900; /* Let the C library deal with * daylight savings time. */ tm.tm_isdst = -1; /* Ugly hack, in case current locale * is not English. This code is taken * from log.c. */ if (strcmp(month, "Jan") == 0) { tm.tm_mon= 0; } else if (strcmp(month, "Feb") == 0) { tm.tm_mon = 1; } else if (strcmp(month, "Mar") == 0) { tm.tm_mon = 2; } else if (strcmp(month, "Apr") == 0) { tm.tm_mon = 3; } else if (strcmp(month, "May") == 0) { tm.tm_mon = 4; } else if (strcmp(month, "Jun") == 0) { tm.tm_mon = 5; } else if (strcmp(month, "Jul") == 0) { tm.tm_mon = 6; } else if (strcmp(month, "Aug") == 0) { tm.tm_mon = 7; } else if (strcmp(month, "Sep") == 0) { tm.tm_mon = 8; } else if (strcmp(month, "Oct") == 0) { tm.tm_mon = 9; } else if (strcmp(month, "Nov") == 0) { tm.tm_mon = 10; } else if (strcmp(month, "Dec") == 0) { tm.tm_mon = 11; } data = g_new0( struct trillian_logger_data, 1); data->path = g_strdup(path); data->offset = offset; data->length = 0; data->their_nickname = g_strdup(their_nickname); /* XXX: Look into this later... Should we pass in a struct tm? */ log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); log->logger = trillian_logger; log->logger_data = data; list = g_list_append(list, log); } } } c++; line = c; last_line_offset = offset; } g_free(contents); } g_free(path); g_free(prpl_name); return list;}static char * trillian_logger_read (PurpleLog *log, PurpleLogReadFlags *flags){ struct trillian_logger_data *data; char *read; FILE *file; PurpleBuddy *buddy; char *escaped; GString *formatted; char *c; const char *line; g_return_val_if_fail(log != NULL, g_strdup("")); data = log->logger_data; g_return_val_if_fail(data->path != NULL, g_strdup("")); g_return_val_if_fail(data->length > 0, g_strdup("")); g_return_val_if_fail(data->their_nickname != NULL, g_strdup("")); purple_debug(PURPLE_DEBUG_INFO, "Trillian log read", "Reading %s\n", data->path); read = g_malloc(data->length + 2); file = g_fopen(data->path, "rb"); fseek(file, data->offset, SEEK_SET); fread(read, data->length, 1, file); fclose(file); if (read[data->length-1] == '\n') { read[data->length] = '\0'; } else { read[data->length] = '\n'; read[data->length+1] = '\0'; } /* Load miscellaneous data. */ buddy = purple_find_buddy(log->account, log->name); escaped = g_markup_escape_text(read, -1); g_free(read); read = escaped; /* Apply formatting... */ formatted = g_string_sized_new(strlen(read)); c = read; line = read; while (c) { const char *link; const char *footer = NULL; GString *temp = NULL; if ((c = strstr(c, "\n"))) { *c = '\0'; c++; } /* Convert links. * * The format is (Link: URL)URL * So, I want to find each occurance of "(Link: " and replace that chunk with: * <a href=" * Then, replace the next ")" with: * "> * Then, replace the next " " (or add this if the end-of-line is reached) with: * </a> * * As implemented, this isn't perfect, but it should cover common cases. */ while (line && (link = strstr(line, "(Link: "))) { const char *tmp = link; link += 7; if (*link) { char *end_paren; char *space; if (!(end_paren = strstr(link, ")"))) { /* Something is not as we expect. Bail out. */ break; } if (!temp) temp = g_string_sized_new(c ? (c - 1 - line) : strlen(line)); g_string_append_len(temp, line, (tmp - line)); /* Start an <a> tag. */ g_string_append(temp, "<a href=\""); /* Append up to the ) */ g_string_append_len(temp, link, end_paren - link); /* Finish the <a> tag. */ g_string_append(temp, "\">"); /* The \r is a bit of a hack to keep there from being a \r in * the link text, which may not matter. */ if ((space = strstr(end_paren, " ")) || (space = strstr(end_paren, "\r"))) { g_string_append_len(temp, end_paren + 1, space - end_paren - 1); /* Close the <a> tag. */ g_string_append(temp, "</a>"); space++; } else { /* There is no space before the end of the line. */ g_string_append(temp, end_paren + 1); /* Close the <a> tag. */ g_string_append(temp, "</a>"); } line = space; } else { /* Something is not as we expect. Bail out. */ break; } } if (temp) { if (line) g_string_append(temp, line); line = temp->str; } if (*line == '[') { const char *timestamp; if ((timestamp = strstr(line, "]"))) { line++; /* TODO: Parse the timestamp and convert it to Purple's format. */ g_string_append(formatted, "<font size=\"2\">("); g_string_append_len(formatted, line, (timestamp - line)); g_string_append(formatted,")</font> "); line = timestamp + 1; if (line[0] && line[1]) line++; } if (purple_str_has_prefix(line, "*** ")) { line += (sizeof("*** ") - 1); g_string_append(formatted, "<b>"); footer = "</b>"; if (purple_str_has_prefix(line, "NOTE: This user is offline.")) { line = _("User is offline."); } else if (purple_str_has_prefix(line, "NOTE: Your status is currently set to ")) { line += (sizeof("NOTE: ") - 1); } else if (purple_str_has_prefix(line, "Auto-response sent to ")) { g_string_append(formatted, _("Auto-response sent:")); while (*line && *line != ':') line++; if (*line) line++; g_string_append(formatted, "</b>"); footer = NULL; } else if (strstr(line, " signed off ")) { if (buddy != NULL && buddy->alias) g_string_append_printf(formatted, _("%s has signed off."), buddy->alias); else g_string_append_printf(formatted, _("%s has signed off."), log->name); line = ""; } else if (strstr(line, " signed on ")) { if (buddy != NULL && buddy->alias) g_string_append(formatted, buddy->alias); else g_string_append(formatted, log->name); line = " logged in."; } else if (purple_str_has_prefix(line, "One or more messages may have been undeliverable.")) { g_string_append(formatted, "<span style=\"color: #ff0000;\">"); g_string_append(formatted, _("One or more messages may have been " "undeliverable.")); line = ""; footer = "</span></b>"; } else if (purple_str_has_prefix(line, "You have been disconnected.")) { g_string_append(formatted, "<span style=\"color: #ff0000;\">"); g_string_append(formatted, _("You were disconnected from the server.")); line = ""; footer = "</span></b>"; } else if (purple_str_has_prefix(line, "You are currently disconnected.")) { g_string_append(formatted, "<span style=\"color: #ff0000;\">"); line = _("You are currently disconnected. Messages " "will not be received unless you are " "logged in."); footer = "</span></b>"; } else if (purple_str_has_prefix(line, "Your previous message has not been sent.")) { g_string_append(formatted, "<span style=\"color: #ff0000;\">"); if (purple_str_has_prefix(line, "Your previous message has not been sent. "
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?