X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=sbr%2Fmessage_id.c;h=bb71313021501967de473e571a3d15de84efaf45;hb=293b37f3c3eab8af5c87c9ad8ee9df89c998cf48;hp=d0a6dd9dbd2da36dc2183124fbc88c4bef24cd42;hpb=9f8f8b1e1d553774865f2c177191c359c3dc652c;p=mmh diff --git a/sbr/message_id.c b/sbr/message_id.c index d0a6dd9..bb71313 100644 --- a/sbr/message_id.c +++ b/sbr/message_id.c @@ -8,15 +8,15 @@ */ #include -#include /* for getpid() */ -#include /* for gettimeofday() */ +#include /* for getpid() */ +#include /* for gettimeofday() */ #include -#define NMH_MESSAGE_ID_LOCALNAME 0 -#define NMH_MESSAGE_ID_RANDOM 1 - -static int message_id_style = NMH_MESSAGE_ID_LOCALNAME; +static enum { + NMH_MESSAGE_ID_LOCALNAME, + NMH_MESSAGE_ID_RANDOM +} message_id_style = NMH_MESSAGE_ID_LOCALNAME; static char message_id_[BUFSIZ]; @@ -37,51 +37,75 @@ save_message_id_style (const char *value) { char * message_id (time_t tclock, int content_id) { - if (message_id_style == NMH_MESSAGE_ID_LOCALNAME) { - char *format = content_id ? "<%d.%ld.%%d@%s>" : "<%d.%ld@%s>"; - - snprintf (message_id_, sizeof message_id_, format, - (int) getpid (), (long) tclock, LocalName (1)); - } else if (message_id_style == NMH_MESSAGE_ID_RANDOM) { - char *format = content_id ? "<%d-%ld.%06ld%%d@%s>" : "<%d-%ld.%06ld@%s>"; - /* Use a sequence of digits divisible by 3 because that will - expand to base64 without any waste. Must be shorter than 58, - see below. */ - unsigned char rnd[12]; - - if (m_rand (rnd, sizeof rnd) == 0) { - pid_t pid; - struct timeval now; - /* All we really need is 4 * [sizeof rnd/3] + 2, as long as the - base64 encoding stays shorter than 76 bytes so embedded - newlines aren't necessary. But use double the sizeof rnd - just to be safe. */ - unsigned char rnd_base64[2 * sizeof rnd]; - int i; - - writeBase64 (rnd, sizeof rnd, rnd_base64); - - for (i = strlen ((const char *) rnd_base64) - 1; - i > 0 && iscntrl (rnd_base64[i]); - --i) { - /* Remove trailing newline. rnd_base64 had better be shorter - than 76 characters, so don't bother to look for embedded - newlines. */ - rnd_base64[i] = '\0'; - } - - /* Neither of these can fail according to the POSIX spec. */ - pid = getpid (); - gettimeofday (&now, 0); + switch (message_id_style) { + case NMH_MESSAGE_ID_LOCALNAME: { + char *format = content_id ? "<%d.%ld.%%d@%s>" : "<%d.%ld@%s>"; snprintf (message_id_, sizeof message_id_, format, - pid, (long) now.tv_sec, (long) now.tv_usec, rnd_base64); + (int) getpid (), (long) tclock, LocalName (1)); + + break; } - } else { - /* Should never get here. */ - adios (0, "invalid message id style \"%s\"", message_id_style); - } + case NMH_MESSAGE_ID_RANDOM: { + char *format = content_id + ? "<%d-%ld.%06ld%%d@%.*s.%.*s.%.*s>" + : "<%d-%ld.%06ld@%.*s.%.*s.%.*s>"; + /* Use a sequence of digits divisible by 3 because that will + expand to base64 without any waste. Must be shorter than 58, + see below. */ + unsigned char rnd[9]; + /* The part after the '@' is divided into thirds. The base64 + encoded string will be 4/3 the size of rnd. */ + size_t one_third = sizeof rnd * 4/3/3; + + if (m_rand (rnd, sizeof rnd) == 0) { + struct timeval now; + /* All we really need is 4 * [sizeof rnd/3] + 2, as long as + the base64 encoding stays shorter than 76 bytes so embedded + newlines aren't necessary. But use double the sizeof rnd + just to be safe. */ + unsigned char rnd_base64[2 * sizeof rnd]; + unsigned char *cp; + int i; + + writeBase64 (rnd, sizeof rnd, rnd_base64); + + for (i = strlen ((const char *) rnd_base64) - 1; + i > 0 && iscntrl (rnd_base64[i]); + --i) { + /* Remove trailing newline. rnd_base64 had better be + shorter than 76 characters, so don't bother to look for + embedded newlines. */ + rnd_base64[i] = '\0'; + } + + /* Try to make the base64 string look a little more like a + hostname by replacing + with - and / with _. */ + for (cp = rnd_base64; *cp; ++cp) { + if (*cp == '+') { + *cp = '-'; + } else if (*cp == '/') { + *cp = '_'; + } + } + + /* gettimeofday() and getpid() shouldn't fail on POSIX platforms. */ + gettimeofday (&now, 0); + + /* The format string inserts a couple of dots, for the benefit + of spam filters that want to see a message id with a final + part that resembles a hostname. */ + snprintf (message_id_, sizeof message_id_, format, + getpid (), (long) now.tv_sec, (long) now.tv_usec, + one_third, rnd_base64, + one_third, &rnd_base64[one_third], + one_third, &rnd_base64[2*one_third]); + } + + break; + } + } return message_id_; }