summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README1
-rw-r--r--TODO4
-rw-r--r--blabouncer.c7
-rw-r--r--blabouncer.conf.example3
-rw-r--r--config.c3
-rw-r--r--functions.c11
-rw-r--r--replay.c42
-rw-r--r--replay.h3
-rw-r--r--structures.h1
9 files changed, 57 insertions, 18 deletions
diff --git a/README b/README
index ff5e5e7..86f2ae4 100644
--- a/README
+++ b/README
@@ -32,6 +32,7 @@ These options can be changed by issuing a BLABOUNCER REHASH command or by sendin
- nick3
- replaymode
- replayseconds
+ - replaydates
- password
- logging
- replaylogging
diff --git a/TODO b/TODO
index 4e76790..0714ace 100644
--- a/TODO
+++ b/TODO
@@ -4,8 +4,6 @@ Support arrays or similar in the configuration file (for nick(s), connectcommand
All the TODOs sprinkled throughout the code!
-Option to include date in replay log replay.
-
(I think) replay log can cause non-existent user to appear in channel (e.g. ~19:00 on 12/08/2019 for me)
Do server operator messages and commands work?
@@ -13,3 +11,5 @@ Do server operator messages and commands work?
(I vaguely recall) some unwanted stuff (channel ban info?) was relayed to another client upon a client connecting.
PM replay chat in a channel (or perhaps a random channel?) e.g. replay on 06/09/2019 at 17:05 from 13:49 in #insomnia - maybe a client thing.
+
+Ensure replayed lines don't exceed IRC message maximum length due to inserted time/datestamp.
diff --git a/blabouncer.c b/blabouncer.c
index 17ce41c..7d8dc06 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -935,6 +935,13 @@ int main(int argc, char *argv[]) {
exit(1);
}
+ // Should sending replay logs include a datestamp?
+ settings.replaydates= getconfint("replaydates", settings.conffile);
+ if (errno == ECONFINT) {
+ printf("main(): error getting 'replaydates' from configuration file.\n");
+ exit(1);
+ }
+
// What is the bouncer password?
if (!getconfstr("password", settings.conffile, settings.password)) {
printf("main(): error getting 'password' from configuration file.\n");
diff --git a/blabouncer.conf.example b/blabouncer.conf.example
index 76df607..12727c9 100644
--- a/blabouncer.conf.example
+++ b/blabouncer.conf.example
@@ -32,6 +32,9 @@ replaymode = "time"
# How many seconds of replay log should be sent to connecting clients if replaymode = "time"
replayseconds = "600"
+# Should replay log timestamps include the date when replaying? ("1" for yes or "0" for no)
+replaydates = "0"
+
# Connect password clients must provided to connect
password = "bananas"
diff --git a/config.c b/config.c
index 18e2178..cea404c 100644
--- a/config.c
+++ b/config.c
@@ -185,6 +185,9 @@ int createconfigfile(char *filename) {
"# How many seconds of replay log should be sent to connecting clients if replaymode = \"time\"\n"
"replayseconds = \"600\"\n"
"\n"
+ "# Should replay log timestamps include the date when replaying? (\"1\" for yes or \"0\" for no)\n"
+ "replaydates = \"0\"\n"
+ "\n"
"# Connect password clients must provided to connect\n"
"password = \"bananas\"\n"
"\n"
diff --git a/functions.c b/functions.c
index b9f1080..bbbd9dd 100644
--- a/functions.c
+++ b/functions.c
@@ -811,7 +811,7 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set
// Replay those lines!
for (int i = 0; i < numlines; i++) {
- if (!readreplayline(replayseconds, i, outgoingmsg, settings->basedir)) {
+ if (!readreplayline(replayseconds, i, outgoingmsg, settings->basedir, settings->replaydates)) {
debugprint(DEBUG_CRIT, "Error requesting replay line.\n");
return 0;
}
@@ -1124,6 +1124,15 @@ int rehash(struct settings *settings, char *failuremsg) {
return 0;
}
+ // Should sending replay logs include a datestamp?
+ int oldreplaydates = settings->replaydates;
+ settings->replaydates = getconfint("replaydates", settings->conffile);
+ if (errno == ECONFINT) {
+ settings->replaydates = oldreplaydates;
+ strcpy(failuremsg, "error getting 'replaydates' from configuration file");
+ return 0;
+ }
+
// What is the password?
char oldpassword[MAXCHAR];
strcpy(oldpassword, settings->password);
diff --git a/replay.c b/replay.c
index 5e54f28..412ed7c 100644
--- a/replay.c
+++ b/replay.c
@@ -83,16 +83,21 @@ int striptimestamp(char *str) {
// 1557592901 :foo!bar@baz PRIVMSG foo :hello world
// And convert it to:
// :foo!bar@baz PRIVMSG foo :[17:41:41] hello world
+// Or the same but e.g. [DD/MM/YY HH:MM:SS] if replaydates == 1.
// Only inserts the formatted time for PRIVMSGs at the moment (and maybe only needs to!).
-void formattime(char *str) {
+void formattime(char *str, int replaydates) {
// Extract the timestamp for conversion into [HH:MM:SS]
char timestr[TIMELEN];
sprintf(timestr, "%d", gettimestamp(str)); // Convert int time to string time
struct tm tm;
strptime(timestr, "%s", &tm);
- char timestampf[TIMELEN]; // Formatted timestamp
- // Convert into [HH:MM:SS]
- strftime(timestampf, TIMELEN, "[%H:%M:%S]", &tm);
+ char timestampf[DATETIMELEN]; // Formatted timestamp
+ // Convert into [HH:MM:SS] or e.g. [DD/MM/YY HH:MM:SS]
+ if (replaydates) {
+ strftime(timestampf, DATETIMELEN, "[%x %H:%M:%S]", &tm);
+ } else {
+ strftime(timestampf, DATETIMELEN, "[%H:%M:%S]", &tm);
+ }
// Strip the original unixtimestamp
striptimestamp(str);
@@ -144,22 +149,30 @@ void formattime(char *str) {
// Second bit (:foo!bar@baz PRIVMSG foo :[HH:MM:SS])
int j = 0;
- for (int i = realpos; i < TIMELEN + realpos - 1; i++) { // -1 to avoid the null char from timestampf
+ for (size_t i = realpos; i < strlen(timestampf) + realpos; i++) {
newline[i] = timestampf[j];
j++;
}
// Insert a space after the formatted timestamp
- newline[TIMELEN + realpos - 1] = ' ';
+ newline[strlen(timestampf) + realpos] = ' ';
+ newline[strlen(timestampf) + realpos + 1] = '\0';
- // Final bit (the original PRIVMSG contents)
- for (int i = TIMELEN + realpos; i < len + TIMELEN; i++) {
- newline[i] = str[i - TIMELEN];
+ // Record length of temporary newline string and original real message (after the colon)
+ size_t newlinelen = strlen(newline);
+ size_t msglen = strlen(str) - realpos - 2; // - 2 to ignore leading colon and null terminator
+
+ // Append the real message to the temporary newline string
+ for (size_t i = 0; i < strlen(str) - realpos - 2; i++) {
+ newline[newlinelen + i] = str[realpos + i];
}
+ // Null terminate it
+ newline[newlinelen + msglen] = '\0';
+
// Copy the whole thing back to str and null terminate
- strncpy(str, newline, len + TIMELEN);
- str[len + TIMELEN] = '\0';
+ strncpy(str, newline, len + strlen(timestampf));
+ str[len + strlen(timestampf)] = '\0';
}
// Return the number of lines in the replay log since 'seconds' seconds ago, or -1 if there a problem.
@@ -208,10 +221,11 @@ int replaylines(int seconds, char *basedir) {
// Set 'str' to the line in the log with a timestamp of greater than 'seconds'
// seconds ago, plus however many lines 'linenum' is set to. 'basedir' is the
// directory in which to find 'replay.log'.
-// Also modify the line to include a timestamp in the form "[HH:MM:SS]".
+// Also modify the line to include a timestamp in the form "[HH:MM:SS]", or [DD/MM/YY HH:MM:SS]
+// if replaydates == 1.
// Returns 1 on success, or 0 on failure.
// TODO - This is horribly inefficient since it re-reads the entire file each call, rewrite this!
-int readreplayline(int seconds, int linenum, char *str, char *basedir) {
+int readreplayline(int seconds, int linenum, char *str, char *basedir, int replaydates) {
FILE *fp;
char line[MAXCHAR];
char filename[PATH_MAX];
@@ -246,7 +260,7 @@ int readreplayline(int seconds, int linenum, char *str, char *basedir) {
// ...and it is the current requested line then return it
if (count == linenum) {
// Insert our formatted [HH:MM:SS] timestamp into the message
- formattime(line);
+ formattime(line, replaydates);
strncpy(str, line, strlen(line));
str[strlen(line)] = '\0';
diff --git a/replay.h b/replay.h
index 5ae9994..c3f23f9 100644
--- a/replay.h
+++ b/replay.h
@@ -36,10 +36,11 @@
#define MAXCHAR 1000
#define TIMELEN 11 // 32-bit unixtime is up to 10 characters (+1 for null char) // TODO - Make this Year 2038 proof
#define TIMELENF 11 // [HH:MM:SS] = 10 characters + 1 for null char
+#define DATETIMELEN 50 // Should be enough for a full datetime string // TODO - Is it!? I think it will only ever be as long as [DD/MM/YY HH:MM:SS] (20 including null)
int replaylines(int seconds, char *basedir);
-int readreplayline(int seconds, int linenum, char *str, char *basedir);
+int readreplayline(int seconds, int linenum, char *str, char *basedir, int replaydates);
// Returns the number of seconds ago that 'nick' last spoke, or -1 if there is a problem.
// 'basedir' is the directory in which to find 'replay.log'.
diff --git a/structures.h b/structures.h
index a959a92..66c34d0 100644
--- a/structures.h
+++ b/structures.h
@@ -80,6 +80,7 @@ struct settings {
int replaylogging;
int debugkeep;
int background; // Whether or not we're running in the background (detached from the terminal as a daemon)
+ int replaydates; // Whether or not to include datestamps when replaying the replay log
};
// Structure of a connected clien, their socket/file descriptors, their authentication status, and their OpenSSL structures