diff options
author | Luke Bratch <luke@bratch.co.uk> | 2019-05-19 22:08:40 +0100 |
---|---|---|
committer | Luke Bratch <luke@bratch.co.uk> | 2019-05-19 22:08:40 +0100 |
commit | 62e67b22e721d2e08c4a4d5dbc85e404fd2ba507 (patch) | |
tree | d0bf4c580cdf36f3f677dcf817b9f529b78f2ea9 | |
parent | 47ab329212bf47f2f70fc7210e4d233210279944 (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-- | TODO | 9 | ||||
-rw-r--r-- | blabouncer.c | 78 |
2 files changed, 82 insertions, 5 deletions
@@ -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 |