diff options
| author | Luke Bratch <luke@bratch.co.uk> | 2019-09-07 12:43:04 +0100 | 
|---|---|---|
| committer | Luke Bratch <luke@bratch.co.uk> | 2019-09-07 12:43:04 +0100 | 
| commit | e4d1706031540ae74ff104c44adeb735ee0bfcf4 (patch) | |
| tree | 46e12bb133f0810bf9f535ad8f34a7415746c31f | |
| parent | 38bd2b2761b7d0f556945ffad78f73536e12e157 (diff) | |
Add a configuration option to include the date in the timestamp when replaying the replay log.
| -rw-r--r-- | README | 1 | ||||
| -rw-r--r-- | TODO | 4 | ||||
| -rw-r--r-- | blabouncer.c | 7 | ||||
| -rw-r--r-- | blabouncer.conf.example | 3 | ||||
| -rw-r--r-- | config.c | 3 | ||||
| -rw-r--r-- | functions.c | 11 | ||||
| -rw-r--r-- | replay.c | 42 | ||||
| -rw-r--r-- | replay.h | 3 | ||||
| -rw-r--r-- | structures.h | 1 | 
9 files changed, 57 insertions, 18 deletions
@@ -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 @@ -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" @@ -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); @@ -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'; @@ -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  | 
