summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-05-19 22:08:40 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-05-19 22:08:40 +0100
commit62e67b22e721d2e08c4a4d5dbc85e404fd2ba507 (patch)
treed0bf4c580cdf36f3f677dcf817b9f529b78f2ea9
parent47ab329212bf47f2f70fc7210e4d233210279944 (diff)
Don't log replay TOPIC/JOIN/PART if we're not in that channel, and don't ever replay them if they were from ourself.
-rw-r--r--TODO9
-rw-r--r--blabouncer.c78
2 files changed, 82 insertions, 5 deletions
diff --git a/TODO b/TODO
index 7140402..613ded5 100644
--- a/TODO
+++ b/TODO
@@ -2,4 +2,11 @@ Move debug output into some debug function that can be enabled/disabled.
Automatically try new nicks if there's no more configured nicks to try (e.g. if foo is in use, try foo1, foo2, etc.)
-Don't replay logs for channels the user isn't currently in or clients will take JOINs/PARTs literally, plus channel info will be missing.
+Add various auto replay options:
+ - All logs since the final client disconnected
+ - All logs since the most recent client connect/disconnect
+ - All logs since *you* last sent a message
+ - All logs since X seconds ago (already implemented)
+ - All logs since the current client last disconnected (track clients with some special token the client auto sends on connect)
+
+Allow log replay time to be specified with days:hours:minutes:seconds.
diff --git a/blabouncer.c b/blabouncer.c
index a6a811a..6d473c9 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -417,7 +417,7 @@ int channelgotnames(struct channel *channels, char *name) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
if (channels[i].gotnames) {
printf("channelgotnames(): channel '%s' gotnames was set, returning '%d'.\n", channels[i].name, channels[i].gotnames);
- return channels[i].gotnames;
+ return i;
} else {
printf("channelgotnames(): channel '%s' gotnames was not set, returning '%d'.\n", channels[i].name, channels[i].gotnames);
return 0;
@@ -430,11 +430,34 @@ int channelgotnames(struct channel *channels, char *name) {
return 0;
}
+// Check if we are in a channel named "name" or not.
+// Return 1 if we are, or 0 if not.
+int inchannel(struct channel *channels, char *name) {
+ // Make sure the name doesn't have any trailing CR or LF
+ // (But only if name is at least two characters long already)
+ if (strlen(name) >= 2) {
+ while (name[strlen(name) - 1] == '\r' || name[strlen(name) - 1] == '\n') {
+ name[strlen(name) - 1] = '\0';
+ }
+ }
+
+ for (int i = 0; i < MAXCHANNELS; i++) {
+ if (strncmp(channels[i].name, name, strlen(name)) == 0) {
+ printf("inchannel(): in channel '%s'.\n", name);
+ return 1;
+ }
+ }
+
+ // We're not in the channel
+ printf("inchannel(): NOT in channel '%s'.\n", name);
+ return 0;
+}
+
// Send the requested number of lines of replay log to the requested client
// 'sourcefd' is the client to send to, and replayseconds is the number of
// seconds of replay to replay.
// Returns 1 for success or 0 for failure.
-int doreplay(int sourcefd, int replayseconds, struct client *clients, struct settings *settings, struct ircdstrings *ircdstrings) {
+int doreplay(int sourcefd, int replayseconds, struct client *clients, struct settings *settings, struct ircdstrings *ircdstrings, struct channel *channels) {
char outgoingmsg[MAXDATASIZE];
// Figure out how many lines to replay
@@ -460,6 +483,53 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set
printf("Error requesting replay line.\n");
exit(1);
}
+
+ // Check if the replay line is a TOPIC, a JOIN, or a PART so we don't
+ // replay those if we are not currently in the channel they are from
+ // otherwise clients and state go a bit mad.
+ // Never replay them if they are from us.
+
+ // Copy to a temporary string
+ char *strcopy = strdup(outgoingmsg);
+ // Keep track of initial pointer for free()ing later
+ char *strcopyPtr = strcopy;
+
+ // Build array of each space-separated token
+ char tokens[3][MAXDATASIZE];
+ char *token;
+
+ for (int j = 0; j < 3; j++) {
+ // Try to split
+ if ((token = strsep(&strcopy, " ")) == NULL) {
+ printf("doreplay(): error splitting string on iteration %d, exiting!\n", j);
+ exit(1);
+ }
+ // Copy into the token array (strlen + 1 to get the NULL terminator)
+ strncpy(tokens[j], token, strlen(token) + 1);
+ }
+
+ if (strncmp(tokens[1], "TOPIC", strlen("TOPIC")) == 0 ||
+ strncmp(tokens[1], "JOIN", strlen("JOIN")) == 0 ||
+ strncmp(tokens[1], "PART", strlen("PART")) == 0) {
+ // Skip over colon if present in channel name
+ int offset = 0;
+ if (tokens[2][0] == ':') {
+ offset = 1;
+ }
+
+ // To make sure it's not us
+ extractnickfromprefix(tokens[0]);
+
+ // Check if we're currently in this channel or if the log line is from us
+ if (!inchannel(channels, tokens[2] + offset) || strncmp(tokens[0], ircdstrings->ircnick, strlen(tokens[0])) == 0) {
+ printf("Not sending '%s' replay line '%s'.\n", tokens[1], outgoingmsg);
+ free(strcopyPtr);
+ continue;
+ }
+ }
+
+ free(strcopyPtr);
+
printf("Sending replay line: '%s'.\n", outgoingmsg);
sendtoclient(sourcefd, outgoingmsg, clients, settings);
}
@@ -1303,7 +1373,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli
clients[arrindex(clients, sourcefd)].registered = 1;
// Catch the client up with the default number of seconds of replay
- doreplay(sourcefd, settings->replayseconds, clients, settings, ircdstrings);
+ doreplay(sourcefd, settings->replayseconds, clients, settings, ircdstrings, channels);
free(strcopyPtr);
return 1;
@@ -1488,7 +1558,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli
return 1;
}
- doreplay(sourcefd, replayseconds, clients, settings, ircdstrings);
+ doreplay(sourcefd, replayseconds, clients, settings, ircdstrings, channels);
free(strcopyPtr);
return 1;
// Unrecognised BLABOUNCER command received, send some help instructions