1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
/* $Id: messageid.c 8786 2009-11-15 09:26:49Z iulius $
**
** Routines for message-IDs: generation and checks.
*/
#include "config.h"
#include "clibrary.h"
#include <ctype.h>
#include <time.h>
#include "inn/innconf.h"
#include "inn/libinn.h"
#include "inn/nntp.h"
/* Scale time back a bit, for shorter message-IDs. */
#define OFFSET 673416000L
/*
** Flag array, indexed by character. Character classes for message-IDs.
*/
static char midcclass[256];
#define CC_MSGID_ATOM 01
#define CC_MSGID_NORM 02
#define midnormchar(c) ((midcclass[(unsigned char)(c)] & CC_MSGID_NORM) != 0)
#define midatomchar(c) ((midcclass[(unsigned char)(c)] & CC_MSGID_ATOM) != 0)
char *
GenerateMessageID(char *domain)
{
static char buff[SMBUF];
static int count;
char *p;
char sec32[10];
char pid32[10];
time_t now;
now = time(NULL);
Radix32(now - OFFSET, sec32);
Radix32(getpid(), pid32);
if ((domain != NULL && innconf->domain == NULL) ||
(domain != NULL && innconf->domain != NULL
&& strcmp(domain, innconf->domain) != 0)) {
p = domain;
} else {
if ((p = GetFQDN(domain)) == NULL)
return NULL;
}
snprintf(buff, sizeof(buff), "<%s$%s$%d@%s>", sec32, pid32, ++count, p);
return buff;
}
/*
** Initialize the character class tables.
*/
void
InitializeMessageIDcclass(void)
{
const unsigned char *p;
unsigned int i;
/* Set up the character class tables. These are written a
* little strangely to work around a GCC2.0 bug. */
memset(midcclass, 0, sizeof(midcclass));
p = (const unsigned char*) "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
while ((i = *p++) != 0) {
midcclass[i] = CC_MSGID_ATOM | CC_MSGID_NORM;
}
p = (const unsigned char*) "!#$%&'*+-/=?^_`{|}~";
while ((i = *p++) != 0) {
midcclass[i] = CC_MSGID_ATOM | CC_MSGID_NORM;
}
p = (const unsigned char*) "\"(),.:;<@";
while ((i = *p++) != 0) {
midcclass[i] = CC_MSGID_NORM;
}
}
/*
** According to RFC 3977:
**
** o A message-ID MUST begin with "<", end with ">", and MUST NOT
** contain the latter except at the end.
**
** o A message-ID MUST be between 3 and 250 octets in length.
**
** o A message-ID MUST NOT contain octets other than printable US-ASCII
** characters.
**
** Besides, we check message-ID format based on RFC 5322 grammar, except that
** (as per USEFOR, RFC 5536) whitespace, non-printing, and '>' characters
** are excluded.
** Based on code by Paul Eggert posted to news.software.b on 22-Nov-90
** in <#*tyo2'~n@twinsun.com>, with additional e-mail discussion.
** Thanks, Paul, for the original implementation based upon RFC 1036.
** Updated to RFC 5536 by Julien Elie.
*/
bool
IsValidMessageID(const char *MessageID, bool stripspaces)
{
int c;
const unsigned char *p;
/* Check the length of the message-ID. */
if (MessageID == NULL || strlen(MessageID) > NNTP_MAXLEN_MSGID)
return false;
p = (const unsigned char *) MessageID;
if (stripspaces) {
for (; ISWHITE(*p); p++);
}
/* Scan local-part: "< dot-atom-text". */
if (*p++ != '<')
return false;
for (; ; p++) {
if (midatomchar(*p)) {
while (midatomchar(*++p))
continue;
} else {
return false;
}
if (*p != '.')
break;
}
/* Scan domain part: "@ dot-atom-text|no-fold-literal > \0" */
if (*p++ != '@')
return false;
for ( ; ; p++) {
if (midatomchar(*p)) {
while (midatomchar(*++p))
continue;
} else {
/* no-fold-literal only */
if (p[-1] != '@' || *p++ != '[')
return false;
for ( ; ; ) {
switch (c = *p++) {
default:
if (midnormchar(c)) {
continue;
} else {
return false;
}
case ']':
break;
}
break;
}
break;
}
if (*p != '.')
break;
}
if (*p++ != '>')
return false;
if (stripspaces) {
for (; ISWHITE(*p); p++);
}
return (*p == '\0');
}
|