mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-12-22 17:34:54 +01:00
b31e44c678
The idea is that if a message-id parses with this function, the MUA generating it was probably sane, and in particular it's probably safe to use the result as a parent from In-Reply-to.
126 lines
2.3 KiB
C
126 lines
2.3 KiB
C
#include "notmuch-private.h"
|
|
#include "string-util.h"
|
|
|
|
/* Advance 'str' past any whitespace or RFC 822 comments. A comment is
|
|
* a (potentially nested) parenthesized sequence with '\' used to
|
|
* escape any character (including parentheses).
|
|
*
|
|
* If the sequence to be skipped continues to the end of the string,
|
|
* then 'str' will be left pointing at the final terminating '\0'
|
|
* character.
|
|
*/
|
|
static void
|
|
skip_space_and_comments (const char **str)
|
|
{
|
|
const char *s;
|
|
|
|
s = *str;
|
|
while (*s && (isspace (*s) || *s == '(')) {
|
|
while (*s && isspace (*s))
|
|
s++;
|
|
if (*s == '(') {
|
|
int nesting = 1;
|
|
s++;
|
|
while (*s && nesting) {
|
|
if (*s == '(') {
|
|
nesting++;
|
|
} else if (*s == ')') {
|
|
nesting--;
|
|
} else if (*s == '\\') {
|
|
if (*(s+1))
|
|
s++;
|
|
}
|
|
s++;
|
|
}
|
|
}
|
|
}
|
|
|
|
*str = s;
|
|
}
|
|
|
|
char *
|
|
_notmuch_message_id_parse (void *ctx, const char *message_id, const char **next)
|
|
{
|
|
const char *s, *end;
|
|
char *result;
|
|
|
|
if (message_id == NULL || *message_id == '\0')
|
|
return NULL;
|
|
|
|
s = message_id;
|
|
|
|
skip_space_and_comments (&s);
|
|
|
|
/* Skip any unstructured text as well. */
|
|
while (*s && *s != '<')
|
|
s++;
|
|
|
|
if (*s == '<') {
|
|
s++;
|
|
} else {
|
|
if (next)
|
|
*next = s;
|
|
return NULL;
|
|
}
|
|
|
|
skip_space_and_comments (&s);
|
|
|
|
end = s;
|
|
while (*end && *end != '>')
|
|
end++;
|
|
if (next) {
|
|
if (*end)
|
|
*next = end + 1;
|
|
else
|
|
*next = end;
|
|
}
|
|
|
|
if (end > s && *end == '>')
|
|
end--;
|
|
if (end <= s)
|
|
return NULL;
|
|
|
|
result = talloc_strndup (ctx, s, end - s + 1);
|
|
|
|
/* Finally, collapse any whitespace that is within the message-id
|
|
* itself. */
|
|
{
|
|
char *r;
|
|
int len;
|
|
|
|
for (r = result, len = strlen (r); *r; r++, len--)
|
|
if (*r == ' ' || *r == '\t')
|
|
memmove (r, r+1, len);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
char *
|
|
_notmuch_message_id_parse_strict (void *ctx, const char *message_id)
|
|
{
|
|
const char *s, *end;
|
|
|
|
if (message_id == NULL || *message_id == '\0')
|
|
return NULL;
|
|
|
|
s = skip_space (message_id);
|
|
if (*s == '<')
|
|
s++;
|
|
else
|
|
return NULL;
|
|
|
|
for (end = s; *end && *end != '>'; end++)
|
|
if (isspace (*end))
|
|
return NULL;
|
|
|
|
if (*end != '>')
|
|
return NULL;
|
|
else {
|
|
const char *last = skip_space (end + 1);
|
|
if (*last != '\0')
|
|
return NULL;
|
|
}
|
|
|
|
return talloc_strndup (ctx, s, end - s);
|
|
}
|