Message-ID checking patch
Patrik Rådman <[email protected]>
| Newsgroups | gmane.network.sn |
|---|---|
| Message-ID | <[email protected]> |
Hi,
Attached to this message is a patch that replaces the Message-ID checking
with a looser test based (mainly) on RFC 2822.
For example, the following Message-ID that previously was replaced is
now OK (and all of Chris Niekel's examples as well :)):
<pan.2004.04.05.16.03.57.428926@%hash%.usenet.us.com>
The patch also allows some Message-IDs which are not legal according to RFC
2822, such as these (real-life examples from a mail-to-news server):
<200401170007.i0H07r6r029257@thinkpad..>
<1078336421.650.5.camel@(null)>
<444446RND_LC_CHAR[1-5]3076l$8309258af84$1p39jiz17@apache>
Let me know if this causes any problems...
--
Patrik Rådman · patrik at iki dot fi · http://www.iki.fi/patrik/
"I know this because Tyler knows this."
addr_msgid.patch_3
(text/plain, 6 KB)
Index: addr.c
===================================================================
--- addr.c (revision 34)
+++ addr.c (revision 42)
@@ -5,11 +5,17 @@
* Copyright © 2000- Patrik Rådman.
*/
+/*
+ * The functions here are based (mainly) on RFC 822 / 2822
+ */
+
+#include <stdlib.h>
#include "config.h"
#include "addr.h"
static const char ver_ctrl_id[] = "$Id: addr.c 29 2004-04-24 23:02:38Z patrik $";
+/*
int addr_addrspec(char *buf)
{
char *p;
@@ -29,7 +35,41 @@
p += len;
return (p - buf);
}
+*/
+int addr_idleft (char *buf);
+int addr_idright (char *buf);
+
+/*
+ * Checks for a valid Message-ID
+ */
+
+int addr_msgid (char *buf)
+{
+ char *p;
+ int len;
+
+ p = buf;
+ if (*p != '<')
+ return 0;
+ p++;
+ len = addr_idleft(p);
+ if (!len)
+ return 0;
+ p += len;
+ if (*p != '@')
+ return 0;
+ p++;
+ len = addr_idright(p);
+ if (!len)
+ return 0;
+ p += len;
+ if (*p != '>')
+ return 0;
+ p++;
+ return (p - buf);
+}
+
#define C(x) case x:
int addr_domain(char *buf)
@@ -113,6 +153,10 @@
return 0;
}
+/*
+ * Like strchr() but ignores comments and quoted strings
+ */
+
char *addr_qstrchr(char *str, int find)
{
bool bs, dq, cm;
@@ -177,3 +221,87 @@
*dst = '\0';
return (dst - to);
}
+
+/*
+ * Used by addr_msgid to check the part left of the '@'
+ */
+
+int addr_idleft (char *buf)
+{
+ char *p;
+ bool dq, bs = FALSE;
+
+ p = buf;
+ if ((dq = (*p == '"')))
+ p++;
+
+ for (; *p; p++)
+ if (!bs)
+ switch (*p)
+ {
+ case '"':
+ if (dq && *++p == '@')
+ return (p - buf);
+ else
+ return 0;
+ case '\\':
+ bs = TRUE;
+ break;
+ case '>':
+ return 0;
+ case '@':
+ if (!dq)
+ return (p - buf);
+ else
+ return 0;
+ default:
+ if (*p < 33 || *p > 126)
+ return 0;
+ }
+ else
+ bs = FALSE;
+
+ return 0;
+}
+
+/*
+ * Used by addr_msgid() to check the part right of the '@'
+ */
+
+int addr_idright (char *buf)
+{
+ char *p;
+ bool lb, bs = FALSE;
+
+ p = buf;
+ if ((lb = (*p == '[')))
+ p++;
+
+ for (; *p; p++)
+ if (!bs)
+ switch (*p)
+ {
+ case '[':
+ return 0;
+ case ']':
+ if (lb && *++p == '>')
+ return (p - buf);
+ else
+ return 0;
+ case '\\':
+ bs = TRUE;
+ break;
+ case '>':
+ if (!lb)
+ return (p - buf);
+ else
+ return 0;
+ default:
+ if (*p < 33 || *p > 126)
+ return 0;
+ }
+ else
+ bs = FALSE;
+
+ return 0;
+}
Index: addr.h
===================================================================
--- addr.h (revision 34)
+++ addr.h (revision 42)
@@ -11,8 +11,9 @@
* strchr() but ignores comments and quoted strings.
*/
-extern int addr_addrspec (char *buf);
+/*extern int addr_addrspec (char *buf);*/
extern int addr_domain (char *buf);
extern int addr_localpart (char *buf);
+extern int addr_msgid (char *buf);
extern char *addr_qstrchr (char *str, int find);
extern int addr_unescape (char *from, char *to, int len);
Index: snsend.c
===================================================================
--- snsend.c (revision 34)
+++ snsend.c (revision 42)
@@ -606,16 +606,16 @@
}
HEADER("Message-ID")
{
- int c;
+ int len;
if (msgid.used) break; /* XXX */
for (p = line + hlen + 1; ' ' == *p; p++) ;
- if ('<' != *p++ || (c = addr_addrspec(p)) <= 0)
+ if ('<' != *p || (len = addr_msgid(p)) <= 0)
{
- LOG("append: will replace bad Message-ID \"%s\"", p - 1);
+ LOG("append: will replace bad Message-ID \"%s\"", p);
return 0;
}
- if (b_appendl(&msgid, p, c)) nomem();
+ if (b_appendl(&msgid, p + 1, len - 2)) nomem();
break;
}
if (0 == strncasecmp(line, "X-sn-", 5))
Index: snmail.c
===================================================================
--- snmail.c (revision 34)
+++ snmail.c (revision 42)
@@ -57,6 +57,10 @@
void memerr (void) { fail(2, "No memory"); }
+/*
+ * Creates a Message-ID of the form "pid.time()@hostname"
+ */
+
char *mkid (void)
{
char *buf;
@@ -94,13 +98,16 @@
while ((p = addr_qstrchr(p, '<')))
{
int len;
-
- if ((len = addr_addrspec(++p)) <= 0 || '>' != p[len])
+
+ if ((len = addr_msgid(p)) <= 0)
+ {
+ p++;
continue;
+ }
if (-1 == b_appendl(&references, " <", 2)) memerr();
- if (-1 == b_appendl(&references, buf, addr_unescape(p, buf, len))) memerr();
+ if (-1 == b_appendl(&references, buf, addr_unescape(p + 1, buf, len - 2))) memerr();
if (-1 == b_appendl(&references, ">", 1)) memerr();
- p += len + 1;
+ p += len;
}
}
@@ -157,7 +164,6 @@
int switchline (char *line, int len)
{
char *p;
- int c;
if (check_from_)
{
@@ -200,13 +206,16 @@
if (!messageid)
if (0 == strncasecmp(line, "Message-ID:", 11))
if ((p = addr_qstrchr(line + 11, '<')))
- if ((c = addr_addrspec(++p)) > 0 && '>' == p[c])
+ {
+ int len = 0;
+ if ((len = addr_msgid(p)) > 0)
{
- if (!(messageid = malloc(c + 1)))
+ if (!(messageid = malloc(len - 1)))
memerr();
else
- addr_unescape(p, messageid, c);
+ addr_unescape(p + 1, messageid, len - 2);
}
+ }
break;
case 'n': case 'N':
if (0 == strncasecmp(line, "Newsgroups:", 11))