#include <lib-lib/ascii.h>
#include <lib-lib/str.h>
#include <lib-lib/macros.h>
+#include <lib-lib/file.h>
#include "mutt.h"
#include "handler.h"
return '.'; /* normalized character (we're stricter than RFC2822, 3.6.4) */
}
-static void mutt_gen_localpart (char *buf, unsigned int len, char *fmt)
+static void mutt_gen_localpart(char *buf, unsigned int len, char *fmt)
{
- time_t now;
- struct tm *tm;
- char tmp[SHORT_STRING];
+ time_t now;
+ struct tm *tm;
+ int snlen;
- *buf = '\0';
+ *buf = '\0';
- now = time (NULL);
- tm = gmtime (&now);
+ now = time (NULL);
+ tm = gmtime (&now);
- for (; *fmt; ++fmt) {
- if (*fmt == '%') {
- switch (fmt[1]) {
- case 0:
- return;
- case 'd':
- snprintf (tmp, sizeof (tmp), "%02d", tm->tm_mday);
- str_ncat (buf, len, tmp, 2);
- break;
- case 'h':
- snprintf (tmp, sizeof (tmp), "%02d", tm->tm_hour);
- str_ncat (buf, len, tmp, 2);
- break;
- case 'm':
- snprintf (tmp, sizeof (tmp), "%02d", tm->tm_mon + 1);
- str_ncat (buf, len, tmp, 2);
- break;
- case 'M':
- snprintf (tmp, sizeof (tmp), "%02d", tm->tm_min);
- str_ncat (buf, len, tmp, 2);
- break;
- case 'O':
- snprintf (tmp, sizeof (tmp), "%lo", (unsigned long) now);
- str_ncat (buf, len, tmp, m_strlen(tmp));
- break;
- case 'p':
- snprintf (tmp, sizeof (tmp), "%u", (unsigned int) getpid ());
- str_ncat (buf, len, tmp, m_strlen(tmp));
- break;
- case 'P':
- snprintf (tmp, sizeof (tmp), "%c", MsgIdPfx);
- MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
- str_ncat (buf, len, tmp, 1);
- break;
- case 'r':
- snprintf (tmp, sizeof (tmp), "%u", (unsigned int) rand ());
- str_ncat (buf, len, tmp, m_strlen(tmp));
- break;
- case 'R':
- snprintf (tmp, sizeof (tmp), "%x", (unsigned int) rand ());
- str_ncat (buf, len, tmp, m_strlen(tmp));
- break;
- case 's':
- snprintf (tmp, sizeof (tmp), "%02d", tm->tm_sec);
- str_ncat (buf, len, tmp, 2);
- break;
- case 'T':
- snprintf (tmp, sizeof (tmp), "%u", (unsigned int) now);
- str_ncat (buf, len, tmp, m_strlen(tmp));
- break;
- case 'X':
- snprintf (tmp, sizeof (tmp), "%x", (unsigned int) now);
- str_ncat (buf, len, tmp, m_strlen(tmp));
- break;
- case 'Y':
- snprintf (tmp, sizeof (tmp), "%04d", tm->tm_year + 1900); /* this will break in the year 10000 ;-) */
- str_ncat (buf, len, tmp, 4);
- break;
- case '%':
- str_ncat (buf, len, "%", 1);
- break;
- default:
- str_ncat (buf, len, ".", 1); /* invalid formats are replaced by '.' */
- } /* switch */
- ++fmt;
- }
- else {
- char c;
+ for (; *fmt; ++fmt) {
+#define APPEND_FMT(fmt, ...) \
+ if (len > 0) { \
+ snlen = snprintf(buf, len, fmt, ##__VA_ARGS__); \
+ buf += snlen; \
+ len -= snlen; \
+ }
- c = mutt_normalized_char (*fmt); /* @todo: filter out invalid characters */
- str_ncat (buf, len, &c, 1);
+#define APPEND_BYTE(c) \
+ if (len > 1) { \
+ *buf++ = c; \
+ *buf = '\0'; \
+ len--; \
+ }
+
+ if (*fmt == '%') {
+ switch (fmt[1]) {
+ case 0:
+ return;
+ case 'd':
+ APPEND_FMT("%02d", tm->tm_mday);
+ break;
+ case 'h':
+ APPEND_FMT("%02d", tm->tm_hour);
+ break;
+ case 'm':
+ APPEND_FMT("%02d", tm->tm_mon + 1);
+ break;
+ case 'M':
+ APPEND_FMT("%02d", tm->tm_min);
+ break;
+ case 'O':
+ APPEND_FMT("%lo", (unsigned long)now);
+ break;
+ case 'p':
+ APPEND_FMT("%u", (unsigned int)getpid());
+ break;
+ case 'P':
+ APPEND_FMT("%c", MsgIdPfx);
+ MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
+ break;
+ case 'r':
+ APPEND_FMT("%u", (unsigned int)rand());
+ break;
+ case 'R':
+ APPEND_FMT("%x", (unsigned int)rand());
+ break;
+ case 's':
+ APPEND_FMT("%02d", tm->tm_sec);
+ break;
+ case 'T':
+ APPEND_FMT("%u", (unsigned int) now);
+ break;
+ case 'X':
+ APPEND_FMT("%x", (unsigned int) now);
+ break;
+ case 'Y': /* this will break in the year 10000 ;-) */
+ APPEND_FMT("%04d", tm->tm_year + 1900);
+ break;
+ case '%':
+ APPEND_BYTE('%');
+ break;
+ default: /* invalid formats are replaced by '.' */
+ APPEND_BYTE('.');
+ m_strncat(buf, len, ".", 1);
+ }
+ ++fmt;
+ } else {
+ APPEND_BYTE(mutt_normalized_char(*fmt));
+ }
+
+#undef APPEND_BYTE
+#undef APPEND_FMT
}
- }
}
char *mutt_gen_msgid (void)