From 831d8e5f24b6eaca6cb20a155948d8a6ad2767ad Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 26 Feb 2014 01:51:06 -0500 Subject: [PATCH] implement chat logging --- src/chat.c | 13 +++++- src/log.c | 100 ++++++++++++++++++++++++++++++++++++++++++++ src/log.h | 33 +++++++++++++++ src/toxic_strings.c | 4 +- src/toxic_windows.h | 12 ++++++ 5 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 src/log.c create mode 100644 src/log.h diff --git a/src/chat.c b/src/chat.c index a4d782b..7666215 100644 --- a/src/chat.c +++ b/src/chat.c @@ -94,6 +94,7 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *msg, uint1 } else wprintw(ctx->history, "%s\n", msg); + add_to_log_buf(msg, nick, ctx); alert_window(self, WINDOW_ALERT_1, true); } @@ -137,6 +138,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int num, uint8_t *action, uin wprintw(ctx->history, "* %s %s\n", nick, action); wattroff(ctx->history, COLOR_PAIR(YELLOW)); + add_to_log_buf(action, nick, ctx); alert_window(self, WINDOW_ALERT_1, true); } @@ -263,7 +265,6 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int num, uint8_t filenum, u uint8_t *filename = friends[num].file_receiver.filenames[filenum]; FILE *file_to_save = fopen(filename, "a"); - // we have a problem here, but don't let it segfault if (file_to_save == NULL) { wattron(ctx->history, COLOR_PAIR(RED)); wprintw(ctx->history, "* Error writing to file.\n"); @@ -319,6 +320,8 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *acti wprintw(ctx->history, " * Failed to send action\n"); wattroff(ctx->history, COLOR_PAIR(RED)); } + + add_to_log_buf(action, selfname, ctx); } static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) @@ -478,6 +481,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) if (line[0] == '/') { if (close_win = !strcmp(line, "/close")) { + write_to_log(ctx); int f_num = self->num; delwin(ctx->linewin); delwin(statusbar->topline); @@ -503,6 +507,8 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) } else wprintw(ctx->history, "%s\n", line); + add_to_log_buf(line, selfname, ctx); + if (!statusbar->is_online || tox_send_message(m, self->num, line, strlen(line) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(RED)); wprintw(ctx->history, " * Failed to send message.\n"); @@ -653,6 +659,11 @@ static void chat_onInit(ToxWindow *self, Tox *m) wprintw(ctx->history, "\n\n"); execute(ctx->history, self, m, "/help", CHAT_COMMAND_MODE); wmove(self->window, y2 - CURS_Y_OFFSET, 0); + + if (self->name) { + ctx->log.log_on = true; + init_logging_session(self->name, friends[self->num].pub_key, ctx); + } } ToxWindow new_chat(Tox *m, int friendnum) diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..0b127e8 --- /dev/null +++ b/src/log.c @@ -0,0 +1,100 @@ +/* ctx->log.c + * + * + * Copyright (C) 2014 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Toxic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Toxic. If not, see . + * + */ + +#include +#include +#include + +#include "configdir.h" +#include "toxic_windows.h" +#include "misc_tools.h" + +/* gets the log path by appending to the config dir the name and first 4 chars of key */ +void init_logging_session(uint8_t *name, uint8_t *key, ChatContext *ctx) +{ + if (!ctx->log.log_on) + return; + + char *user_config_dir = get_user_config_dir(); + int path_len = strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(name) + (KEY_IDENT_DIGITS * 2) + 5; + + if (path_len > MAX_STR_SIZE) + return; + + uint8_t ident[KEY_IDENT_DIGITS*2+1]; + sprintf(&ident[0], "%02X", key[0] & 0xff); + sprintf(&ident[2], "%02X", key[2] & 0xff); + ident[KEY_IDENT_DIGITS*2+1] = '\0'; + + snprintf(ctx->log.log_path, MAX_STR_SIZE, "%s%s%s-%s.log", user_config_dir, CONFIGDIR, name, ident); + + FILE *logfile = fopen(ctx->log.log_path, "a"); + + if (logfile == NULL) { + ctx->log.log_on = false; + return; + } + + fprintf(logfile, "\n***NEW SESSION***\n\n"); + + fclose(logfile); + free(user_config_dir); +} + +/* writes contents from a chatcontext's log buffer to respective log file and resets log pos. + This is triggered when the log buffer is full, but may be forced. */ +void write_to_log(ChatContext *ctx) +{ + if (!ctx->log.log_on) + return; + + FILE *logfile = fopen(ctx->log.log_path, "a"); + + if (logfile == NULL) { + ctx->log.log_on = false; + return; + } + + int i; + + for (i = 0; i < ctx->log.pos; ++i) + fprintf(logfile, "%s", ctx->log.log_buf[i]); + + ctx->log.pos = 0; + fclose(logfile); +} + +/* Adds msg to log_buf with timestamp and name. + If buf is full, triggers write_to_log (which sets buf pos to 0) */ +void add_to_log_buf(uint8_t *msg, uint8_t *name, ChatContext *ctx) +{ + if (!ctx->log.log_on) + return; + + struct tm *tminfo = get_time(); + snprintf(ctx->log.log_buf[ctx->log.pos], MAX_LOG_LINE_SIZE, "%04d/%02d/%02d [%02d:%02d:%02d] %s: %s\n", + tminfo->tm_year + 1900, tminfo->tm_mon + 1, tminfo->tm_mday, + tminfo->tm_hour, tminfo->tm_min, tminfo->tm_sec, name, msg); + + if (++(ctx->log.pos) >= MAX_LOG_BUF_LINES) + write_to_log(ctx); +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..01734af --- /dev/null +++ b/src/log.h @@ -0,0 +1,33 @@ +/* log.h + * + * + * Copyright (C) 2014 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Toxic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Toxic. If not, see . + * + */ + +/* gets a log path by appending to the config dir the name and first 4 chars of the pub_key, + writes current date/time to log file. */ +void init_logging_session(uint8_t *name, uint8_t *pub_key, ChatContext *ctx); + +/* Adds msg to log_buf with timestamp and name. + If buf is full, triggers write_to_log (which sets buf pos to 0) */ +void add_to_log_buf(uint8_t *msg, uint8_t *name, ChatContext *ctx); + +/* writes contents from a chatcontext's log buffer to respective log file and resets log pos. + This is triggered automatically when the log buffer is full, but may be forced. */ +void write_to_log(ChatContext *ctx); diff --git a/src/toxic_strings.c b/src/toxic_strings.c index 78abaae..efebc03 100644 --- a/src/toxic_strings.c +++ b/src/toxic_strings.c @@ -146,12 +146,12 @@ void fetch_hist_item(wchar_t *buf, size_t *pos, size_t *len, wchar_t (*hst)[MAX_ { if (key_dir == LN_HIST_MV_UP) { if (--(*hst_pos) < 0) { - (*hst_pos) = 0; + *hst_pos = 0; beep(); } } else { if (++(*hst_pos) >= hst_tot) { - (*hst_pos) = hst_tot; + *hst_pos = hst_tot; reset_buf(buf, pos, len); return; } diff --git a/src/toxic_windows.h b/src/toxic_windows.h index 67b28f0..89ffbba 100644 --- a/src/toxic_windows.h +++ b/src/toxic_windows.h @@ -131,6 +131,16 @@ struct StatusBar { bool is_online; }; +#define MAX_LOG_BUF_LINES 10 /* write log_buf contents to log file after this many lines */ +#define MAX_LOG_LINE_SIZE MAX_STR_SIZE + TOXIC_MAX_NAME_LENGTH + 24 /* extra room for time/date */ + +struct chatlog { + uint8_t log_path[MAX_STR_SIZE]; + uint8_t log_buf[MAX_LOG_BUF_LINES][MAX_LOG_LINE_SIZE]; + int pos; + bool log_on; +}; + #define MAX_LINE_HIST 128 /* chat and groupchat window/buffer holder */ @@ -145,6 +155,8 @@ struct ChatContext { bool self_is_typing; + struct chatlog log; + WINDOW *history; WINDOW *linewin; WINDOW *sidebar;