Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package perl-Email-Address-XS for
openSUSE:Factory checked in at 2022-08-16 17:08:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Email-Address-XS (Old)
and /work/SRC/openSUSE:Factory/.perl-Email-Address-XS.new.1521 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Email-Address-XS"
Tue Aug 16 17:08:34 2022 rev:2 rq:997351 version:1.05
Changes:
--------
---
/work/SRC/openSUSE:Factory/perl-Email-Address-XS/perl-Email-Address-XS.changes
2018-10-08 17:50:48.350072341 +0200
+++
/work/SRC/openSUSE:Factory/.perl-Email-Address-XS.new.1521/perl-Email-Address-XS.changes
2022-08-16 17:08:39.820043163 +0200
@@ -1,0 +2,11 @@
+Mon Aug 8 03:08:40 UTC 2022 - Tina M??ller <[email protected]>
+
+- updated to 1.05
+ see /usr/share/doc/packages/perl-Email-Address-XS/Changes
+
+ 1.05 Sun Aug 07 15:21:35 2022
+ - update dovecot parser from dovecot version 2.3.14
+ - mark the last parsed object as invalid if input string contains
trailing garbage
+ https://github.com/pali/Email-Address-XS/issues/5
+
+-------------------------------------------------------------------
Old:
----
Email-Address-XS-1.04.tar.gz
New:
----
Email-Address-XS-1.05.tar.gz
cpanspec.yml
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ perl-Email-Address-XS.spec ++++++
--- /var/tmp/diff_new_pack.xdrBDR/_old 2022-08-16 17:08:40.296044586 +0200
+++ /var/tmp/diff_new_pack.xdrBDR/_new 2022-08-16 17:08:40.300044598 +0200
@@ -1,7 +1,7 @@
#
# spec file for package perl-Email-Address-XS
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2022 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,20 +12,19 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
+%define cpan_name Email-Address-XS
Name: perl-Email-Address-XS
-Version: 1.04
+Version: 1.05
Release: 0
-%define cpan_name Email-Address-XS
-Summary: Parse and format RFC 5322 email addresses and groups
License: Artistic-1.0 OR GPL-1.0-or-later
-Group: Development/Libraries/Perl
-Url: http://search.cpan.org/dist/Email-Address-XS/
+Summary: Parse and format RFC 5322 email addresses and groups
+URL: https://metacpan.org/release/%{cpan_name}
Source0:
https://cpan.metacpan.org/authors/id/P/PA/PALI/%{cpan_name}-%{version}.tar.gz
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
+Source1: cpanspec.yml
BuildRequires: perl
BuildRequires: perl-macros
%{perl_requires}
@@ -68,15 +67,15 @@
Email::MIME::Header::AddressList.
%prep
-%setup -q -n %{cpan_name}-%{version}
-find . -type f ! -name \*.pl -print0 | xargs -0 chmod 644
+%autosetup -n %{cpan_name}-%{version}
+find . -type f ! -path "*/t/*" ! -name "*.pl" ! -path "*/bin/*" ! -path
"*/script/*" ! -name "configure" -print0 | xargs -0 chmod 644
%build
-%{__perl} Makefile.PL INSTALLDIRS=vendor OPTIMIZE="%{optflags}"
-%{__make} %{?_smp_mflags}
+perl Makefile.PL INSTALLDIRS=vendor OPTIMIZE="%{optflags}"
+%make_build
%check
-%{__make} test
+make test
%install
%perl_make_install
@@ -84,7 +83,6 @@
%perl_gen_filelist
%files -f %{name}.files
-%defattr(-,root,root,755)
%doc Changes README
%changelog
++++++ Email-Address-XS-1.04.tar.gz -> Email-Address-XS-1.05.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/Changes
new/Email-Address-XS-1.05/Changes
--- old/Email-Address-XS-1.04/Changes 2018-06-09 18:24:00.000000000 +0200
+++ new/Email-Address-XS-1.05/Changes 2022-08-07 15:31:30.000000000 +0200
@@ -1,5 +1,10 @@
Revision history for Perl extension Email::Address::XS.
+1.05 Sun Aug 07 15:21:35 2022
+ - update dovecot parser from dovecot version 2.3.14
+ - mark the last parsed object as invalid if input string contains
trailing garbage
+ https://github.com/pali/Email-Address-XS/issues/5
+
1.04 Sat Jun 09 18:20:28 2018
- fix docevot parser to disallow leading dot in dot-atom
- fix generating and validating email addresses with empty user part
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/Email-Address-XS.xs
new/Email-Address-XS-1.05/Email-Address-XS.xs
--- old/Email-Address-XS-1.04/Email-Address-XS.xs 2018-06-09
18:24:00.000000000 +0200
+++ new/Email-Address-XS-1.05/Email-Address-XS.xs 2022-08-07
15:31:30.000000000 +0200
@@ -681,7 +681,7 @@
XSRETURN_EMPTY;
}
PPCODE:
- first_address = message_address_parse(input, input_len, UINT_MAX,
false);
+ first_address = message_address_parse(input, input_len, UINT_MAX,
MESSAGE_ADDRESS_PARSE_FLAG_NON_STRICT_DOTS_AS_INVALID);
count = count_address_groups(first_address);
EXTEND(SP, count * 2);
address = first_address;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/META.json
new/Email-Address-XS-1.05/META.json
--- old/Email-Address-XS-1.04/META.json 2018-06-09 18:25:06.000000000 +0200
+++ new/Email-Address-XS-1.05/META.json 2022-08-07 15:31:38.000000000 +0200
@@ -59,6 +59,6 @@
"web" : "https://github.com/pali/Email-Address-XS"
}
},
- "version" : "1.04",
+ "version" : "1.05",
"x_serialization_backend" : "JSON::PP version 2.97001"
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/META.yml
new/Email-Address-XS-1.05/META.yml
--- old/Email-Address-XS-1.04/META.yml 2018-06-09 18:25:06.000000000 +0200
+++ new/Email-Address-XS-1.05/META.yml 2022-08-07 15:31:38.000000000 +0200
@@ -30,5 +30,5 @@
resources:
bugtracker: https://github.com/pali/Email-Address-XS/issues
repository: git://github.com/pali/Email-Address-XS.git
-version: '1.04'
+version: '1.05'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/dovecot-parser.c
new/Email-Address-XS-1.05/dovecot-parser.c
--- old/Email-Address-XS-1.04/dovecot-parser.c 2018-06-09 18:24:00.000000000
+0200
+++ new/Email-Address-XS-1.05/dovecot-parser.c 2022-08-07 15:31:30.000000000
+0200
@@ -57,6 +57,9 @@
struct rfc822_parser_context {
const unsigned char *data, *end;
string_t *last_comment;
+
+ /* Replace NUL characters with this string */
+ const char *nul_replacement_str;
};
struct message_address_parser_context {
@@ -65,7 +68,7 @@
struct message_address *first_addr, *last_addr, addr;
string_t *str;
- bool fill_missing;
+ bool fill_missing, non_strict_dots, non_strict_dots_as_invalid;
};
static string_t *str_new(size_t initial_size)
@@ -309,6 +312,15 @@
ctx->last_comment = last_comment;
}
+static void rfc822_parser_deinit(struct rfc822_parser_context *ctx)
+{
+ /* make sure the parsing didn't trigger a bug that caused reading
+ past the end pointer. */
+ i_assert(ctx->data <= ctx->end);
+ /* make sure the parser is no longer accessed */
+ ctx->data = ctx->end = NULL;
+}
+
/* The functions below return 1 = more data available, 0 = no more data
available (but a value might have been returned now), -1 = invalid input.
@@ -319,6 +331,7 @@
static int rfc822_skip_comment(struct rfc822_parser_context *ctx)
{
const unsigned char *start;
+ size_t len;
int level = 1;
i_assert(*ctx->data == '(');
@@ -329,6 +342,19 @@
start = ++ctx->data;
for (; ctx->data < ctx->end; ctx->data++) {
switch (*ctx->data) {
+ case '\0':
+ if (ctx->nul_replacement_str != NULL) {
+ if (ctx->last_comment != NULL) {
+ str_append_data(ctx->last_comment,
start,
+ ctx->data - start);
+ str_append(ctx->last_comment,
+ ctx->nul_replacement_str);
+ start = ctx->data + 1;
+ }
+ } else {
+ return -1;
+ }
+ break;
case '(':
level++;
break;
@@ -336,22 +362,41 @@
if (--level == 0) {
if (ctx->last_comment != NULL) {
str_append_data(ctx->last_comment,
start,
- ctx->data - start);
+ ctx->data - start);
}
ctx->data++;
return ctx->data < ctx->end ? 1 : 0;
}
break;
- case '\\':
- if (ctx->last_comment != NULL) {
- str_append_data(ctx->last_comment, start,
- ctx->data - start);
- }
+ case '\n':
+ /* folding whitespace, remove the (CR)LF */
+ if (ctx->last_comment == NULL)
+ break;
+ len = ctx->data - start;
+ if (len > 0 && start[len-1] == '\r')
+ len--;
+ str_append_data(ctx->last_comment, start, len);
start = ctx->data + 1;
-
+ break;
+ case '\\':
ctx->data++;
if (ctx->data >= ctx->end)
return -1;
+#if 0
+ if (*ctx->data == '\r' || *ctx->data == '\n' ||
+ *ctx->data == '\0') {
+ /* quoted-pair doesn't allow CR/LF/NUL.
+ They are part of the obs-qp though, so don't
+ return them as error. */
+ ctx->data--;
+ break;
+ }
+#endif
+ if (ctx->last_comment != NULL) {
+ str_append_data(ctx->last_comment, start,
+ ctx->data - start - 1);
+ }
+ start = ctx->data;
break;
}
}
@@ -379,10 +424,36 @@
return ctx->data < ctx->end ? 1 : 0;
}
+/* Stop at next non-atext char */
+int rfc822_parse_atom(struct rfc822_parser_context *ctx, string_t *str)
+{
+ const unsigned char *start;
+
+ /*
+ atom = [CFWS] 1*atext [CFWS]
+ atext =
+ ; Any character except controls, SP, and specials.
+ */
+ if (ctx->data >= ctx->end || !IS_ATEXT(*ctx->data))
+ return -1;
+
+ for (start = ctx->data++; ctx->data < ctx->end; ctx->data++) {
+ if (IS_ATEXT(*ctx->data))
+ continue;
+
+ str_append_data(str, start, ctx->data - start);
+ return rfc822_skip_lwsp(ctx);
+ }
+
+ str_append_data(str, start, ctx->data - start);
+ return 0;
+}
+
/* Like parse_atom() but don't stop at '.' */
-static int rfc822_parse_dot_atom(struct rfc822_parser_context *ctx, string_t
*str)
+static int rfc822_parse_dot_atom(struct rfc822_parser_context *ctx, string_t
*str, bool stop_trailing_dot)
{
const unsigned char *start;
+ const unsigned char *last_dot_ptr;
bool last_is_dot;
bool dot_problem;
int ret;
@@ -399,6 +470,7 @@
if (ctx->data >= ctx->end || !IS_ATEXT(*ctx->data))
return -1;
+ last_dot_ptr = ctx->data;
last_is_dot = false;
dot_problem = false;
@@ -408,6 +480,10 @@
continue;
}
+#if 0
+ if (start == ctx->data)
+ dot_problem = true;
+#endif
str_append_data(str, start, ctx->data - start);
if (ctx->data - start > 0)
@@ -416,21 +492,30 @@
if ((ret = rfc822_skip_lwsp(ctx)) <= 0)
return (dot_problem && ret >= 0) ? -2 : ret;
- if (*ctx->data != '.')
+ if (*ctx->data != '.') {
+ if (last_is_dot && stop_trailing_dot) {
+ ctx->data = last_dot_ptr;
+ return dot_problem ? -2 : 1;
+ }
return (last_is_dot || dot_problem) ? -2 : 1;
+ }
if (last_is_dot)
dot_problem = true;
+ last_dot_ptr = ctx->data;
ctx->data++;
str_append_c(str, '.');
last_is_dot = true;
- if ((ret = rfc822_skip_lwsp(ctx)) <= 0)
+ if (rfc822_skip_lwsp(ctx) <= 0)
return (dot_problem && ret >= 0) ? -2 : ret;
start = ctx->data;
}
+#if 0
+ i_assert(start != ctx->data);
+#endif
str_append_data(str, start, ctx->data - start);
return dot_problem ? -2 : 0;
}
@@ -439,33 +524,65 @@
static int rfc822_parse_quoted_string(struct rfc822_parser_context *ctx,
string_t *str)
{
const unsigned char *start;
+ bool char_problem;
+ int ret;
size_t len;
i_assert(ctx->data < ctx->end);
i_assert(*ctx->data == '"');
ctx->data++;
+ char_problem = false;
for (start = ctx->data; ctx->data < ctx->end; ctx->data++) {
switch (*ctx->data) {
+ case '\0':
+ if (ctx->nul_replacement_str != NULL) {
+ str_append_data(str, start, ctx->data - start);
+ str_append(str, ctx->nul_replacement_str);
+ start = ctx->data + 1;
+ } else {
+ char_problem = true;
+ }
+ break;
case '"':
str_append_data(str, start, ctx->data - start);
ctx->data++;
- return rfc822_skip_lwsp(ctx);
+ ret = rfc822_skip_lwsp(ctx);
+ return (char_problem && ret >= 0) ? -2 : ret;
+ case '\r':
+ if (ctx->data+1 < ctx->end && *(ctx->data+1) != '\n')
+ char_problem = true;
+ break;
case '\n':
+#if 0
/* folding whitespace, remove the (CR)LF */
len = ctx->data - start;
if (len > 0 && start[len-1] == '\r')
len--;
str_append_data(str, start, len);
start = ctx->data + 1;
+#endif
+ len = ctx->data - start;
+ if (len <= 0 || start[len-1] != '\r')
+ char_problem = true;
break;
case '\\':
ctx->data++;
if (ctx->data >= ctx->end)
return -1;
-
+#if 0
+ if (*ctx->data == '\r' || *ctx->data == '\n' ||
+ *ctx->data == '\0') {
+ /* quoted-pair doesn't allow CR/LF/NUL.
+ They are part of the obs-qp though, so don't
+ return them as error. */
+ ctx->data--;
+ break;
+ }
+#endif
str_append_data(str, start, ctx->data - start - 1);
- start = ctx->data;
+ str_append_c(str, *ctx->data);
+ start = ctx->data+1;
break;
}
}
@@ -503,6 +620,9 @@
static int rfc822_parse_phrase(struct rfc822_parser_context *ctx, string_t
*str)
{
int ret;
+ bool char_problem;
+
+ char_problem = false;
/*
phrase = 1*word / obs-phrase
@@ -521,21 +641,29 @@
else
ret = rfc822_parse_atom_or_dot(ctx, str);
- if (ret <= 0)
- return ret;
+ if (ret <= 0 && ret != -2)
+ return (char_problem && ret == 0) ? -2 : ret;
+
+ if (ret == -2) {
+ char_problem = true;
+ if (ctx->data >= ctx->end)
+ return -2;
+ }
if (!IS_ATEXT(*ctx->data) && *ctx->data != '"'
&& *ctx->data != '.')
break;
str_append_c(str, ' ');
}
- return rfc822_skip_lwsp(ctx);
+ ret = rfc822_skip_lwsp(ctx);
+ return (char_problem && ret >= 0) ? -2 : ret;
}
static int
rfc822_parse_domain_literal(struct rfc822_parser_context *ctx, string_t *str)
{
const unsigned char *start;
+ size_t len;
/*
domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
@@ -548,15 +676,50 @@
i_assert(ctx->data < ctx->end);
i_assert(*ctx->data == '[');
- for (start = ctx->data; ctx->data < ctx->end; ctx->data++) {
- if (*ctx->data == '\\') {
+ for (start = ctx->data++; ctx->data < ctx->end; ctx->data++) {
+ switch (*ctx->data) {
+ case '\0':
+ if (ctx->nul_replacement_str != NULL) {
+ str_append_data(str, start, ctx->data - start);
+ str_append(str, ctx->nul_replacement_str);
+ start = ctx->data + 1;
+ } else {
+ return -1;
+ }
+ break;
+ case '[':
+ /* not allowed */
+ return -1;
+ case ']':
+ str_append_data(str, start, ctx->data - start + 1);
+ ctx->data++;
+ return rfc822_skip_lwsp(ctx);
+ case '\n':
+ /* folding whitespace, remove the (CR)LF */
+ len = ctx->data - start;
+ if (len > 0 && start[len-1] == '\r')
+ len--;
+ str_append_data(str, start, len);
+ start = ctx->data + 1;
+ break;
+ case '\\':
+ /* note: the '\' is preserved in the output */
ctx->data++;
if (ctx->data >= ctx->end)
+ return -1;
+#if 0
+ if (*ctx->data == '\r' || *ctx->data == '\n' ||
+ *ctx->data == '\0') {
+ /* quoted-pair doesn't allow CR/LF/NUL.
+ They are part of the obs-qp though, so don't
+ return them as error. */
+ str_append_data(str, start, ctx->data - start);
+ start = ctx->data;
+ ctx->data--;
break;
- } else if (*ctx->data == ']') {
- ctx->data++;
- str_append_data(str, start, ctx->data - start);
- return rfc822_skip_lwsp(ctx);
+ }
+#endif
+ break;
}
}
@@ -582,7 +745,7 @@
if (*ctx->data == '[')
return rfc822_parse_domain_literal(ctx, str);
else
- return rfc822_parse_dot_atom(ctx, str);
+ return rfc822_parse_dot_atom(ctx, str, false);
}
static void add_address(struct message_address_parser_context *ctx)
@@ -603,9 +766,33 @@
ctx->last_addr = addr;
}
+static int
+parse_nonstrict_dot_atom(struct rfc822_parser_context *ctx, string_t *str)
+{
+ int ret = -1;
+
+ do {
+ while (*ctx->data == '.') {
+ str_append_c(str, '.');
+ ctx->data++;
+ if (ctx->data == ctx->end) {
+ /* @domain is missing, but local-part
+ parsing was successful */
+ return 0;
+ }
+ ret = 1;
+ }
+ if (*ctx->data == '@')
+ break;
+ ret = rfc822_parse_atom(ctx, str);
+ } while (ret > 0 && *ctx->data == '.');
+ return ret;
+}
+
static int parse_local_part(struct message_address_parser_context *ctx)
{
int ret;
+ bool char_problem;
/*
local-part = dot-atom / quoted-string / obs-local-part
@@ -614,12 +801,40 @@
i_assert(ctx->parser.data < ctx->parser.end);
str_truncate(ctx->str, 0);
- if (*ctx->parser.data == '"')
- ret = rfc822_parse_quoted_string(&ctx->parser, ctx->str);
- else
- ret = rfc822_parse_dot_atom(&ctx->parser, ctx->str);
- if (ret < 0 && ret != -2)
- return -1;
+ char_problem = false;
+
+ while (ctx->parser.data < ctx->parser.end) {
+ if (*ctx->parser.data == '"')
+ ret = rfc822_parse_quoted_string(&ctx->parser,
ctx->str);
+ else if (!ctx->non_strict_dots ||
ctx->non_strict_dots_as_invalid)
+ ret = rfc822_parse_dot_atom(&ctx->parser, ctx->str,
true);
+ else
+ ret = parse_nonstrict_dot_atom(&ctx->parser, ctx->str);
+ if (ret < 0 && (ret != -2 || (!ctx->non_strict_dots &&
!ctx->non_strict_dots_as_invalid)))
+ return -1;
+ if (ret == -2)
+ char_problem = true;
+ if (ctx->parser.data >= ctx->parser.end)
+ break;
+ if ((ret = rfc822_skip_lwsp(&ctx->parser)) <= 0)
+ break;
+ if (*ctx->parser.data != '.')
+ break;
+ ctx->parser.data++;
+ if (ctx->parser.data >= ctx->parser.end) {
+ char_problem = true;
+ break;
+ }
+ if ((ret = rfc822_skip_lwsp(&ctx->parser)) <= 0)
+ break;
+ if (ctx->parser.data >= ctx->parser.end || *ctx->parser.data ==
'@') {
+ char_problem = true;
+ break;
+ }
+ }
+
+ if (char_problem || ret < 0)
+ ctx->addr.invalid_syntax = true;
ctx->addr.mailbox = str_ccopy(ctx->str);
ctx->addr.mailbox_len = str_len(ctx->str);
@@ -631,7 +846,7 @@
int ret;
str_truncate(ctx->str, 0);
- if ((ret = rfc822_parse_domain(&ctx->parser, ctx->str)) < 0 && ret !=
-2)
+ if ((ret = rfc822_parse_domain(&ctx->parser, ctx->str)) < 0 && (ret !=
-2 || (!ctx->non_strict_dots && !ctx->non_strict_dots_as_invalid)))
return -1;
ctx->addr.domain = str_ccopy(ctx->str);
@@ -658,7 +873,7 @@
str_append_c(ctx->str, ',');
str_append_c(ctx->str, '@');
- if ((ret = rfc822_parse_domain(&ctx->parser, ctx->str)) <= 0 &&
ret != -2)
+ if ((ret = rfc822_parse_domain(&ctx->parser, ctx->str)) <= 0 &&
(ret != -2 || (!ctx->non_strict_dots && !ctx->non_strict_dots_as_invalid)))
return ret;
if (ret == -2)
@@ -673,7 +888,8 @@
return dot_problem ? -2 : 1;
}
-static int parse_angle_addr(struct message_address_parser_context *ctx)
+static int parse_angle_addr(struct message_address_parser_context *ctx,
+ bool parsing_path)
{
int ret;
@@ -681,11 +897,15 @@
i_assert(*ctx->parser.data == '<');
ctx->parser.data++;
- if ((ret = rfc822_skip_lwsp(&ctx->parser)) <= 0)
- return ret;
+ if (rfc822_skip_lwsp(&ctx->parser) <= 0)
+ return -1;
if (*ctx->parser.data == '@') {
- if ((ret = parse_domain_list(ctx)) <= 0 || *ctx->parser.data !=
':') {
+ if ((ret = parse_domain_list(ctx)) > 0 && *ctx->parser.data ==
':') {
+ ctx->parser.data++;
+ } else if (parsing_path && (ctx->parser.data >= ctx->parser.end
|| *ctx->parser.data != ':')) {
+ return -1;
+ } else {
if (ctx->fill_missing && ret != -2)
ctx->addr.route = strdup("INVALID_ROUTE");
ctx->addr.invalid_syntax = true;
@@ -694,26 +914,23 @@
if (ret == -2)
ctx->parser.data++;
/* try to continue anyway */
- } else {
- ctx->parser.data++;
}
- ctx->parser.data++;
- if ((ret = rfc822_skip_lwsp(&ctx->parser)) <= 0)
- return ret;
+ if (rfc822_skip_lwsp(&ctx->parser) <= 0)
+ return -1;
}
if (*ctx->parser.data == '>') {
/* <> address isn't valid */
} else {
- if ((ret = parse_local_part(ctx)) <= 0 && ret != -2)
- return ret;
+ if ((ret = parse_local_part(ctx)) <= 0 && (ret != -2 ||
(!ctx->non_strict_dots && !ctx->non_strict_dots_as_invalid)))
+ return -1;
if (ret == -2)
ctx->addr.invalid_syntax = true;
if (ctx->parser.data >= ctx->parser.end)
return 0;
if (*ctx->parser.data == '@') {
- if ((ret = parse_domain(ctx)) <= 0 && ret != -2)
- return ret;
+ if ((ret = parse_domain(ctx)) <= 0 && (ret != -2 ||
(!ctx->non_strict_dots && !ctx->non_strict_dots_as_invalid)))
+ return -1;
if (ret == -2)
ctx->addr.invalid_syntax = true;
if (ctx->parser.data >= ctx->parser.end)
@@ -730,15 +947,21 @@
static int parse_name_addr(struct message_address_parser_context *ctx)
{
+ int ret;
+
/*
name-addr = [display-name] angle-addr
display-name = phrase
*/
str_truncate(ctx->str, 0);
- if (rfc822_parse_phrase(&ctx->parser, ctx->str) <= 0 ||
+ ret = rfc822_parse_phrase(&ctx->parser, ctx->str);
+ if ((ret <= 0 && (ret != -2 || (!ctx->non_strict_dots &&
!ctx->non_strict_dots_as_invalid))) ||
*ctx->parser.data != '<')
return -1;
+ if (ret == -2)
+ ctx->addr.invalid_syntax = true;
+
if (str_len(ctx->str) == 0) {
/* Cope with "<address>" without display name */
ctx->addr.name = NULL;
@@ -750,7 +973,7 @@
if (ctx->parser.last_comment != NULL)
str_truncate(ctx->parser.last_comment, 0);
- if (parse_angle_addr(ctx) < 0) {
+ if (parse_angle_addr(ctx, false) < 0) {
/* broken */
if (ctx->fill_missing)
ctx->addr.domain = strdup("SYNTAX_ERROR");
@@ -913,10 +1136,14 @@
display-name = phrase
*/
str_truncate(ctx->str, 0);
- if (rfc822_parse_phrase(&ctx->parser, ctx->str) <= 0 ||
+ ret = rfc822_parse_phrase(&ctx->parser, ctx->str);
+ if ((ret <= 0 && (ret != -2 || (!ctx->non_strict_dots &&
!ctx->non_strict_dots_as_invalid))) ||
*ctx->parser.data != ':')
return -1;
+ if (ret == -2)
+ ctx->addr.invalid_syntax = true;
+
/* from now on don't return -1 even if there are problems, so that
the caller knows this is a group */
ctx->parser.data++;
@@ -989,6 +1216,7 @@
break;
if (ctx->parser.data >= ctx->parser.end ||
*ctx->parser.data != ',') {
+ ctx->last_addr->invalid_syntax = true;
ret = -1;
break;
}
@@ -1087,7 +1315,8 @@
struct message_address *
message_address_parse(const char *input, size_t input_len,
- unsigned int max_addresses, bool fill_missing)
+ unsigned int max_addresses,
+ enum message_address_parse_flags flags)
{
string_t *str;
struct message_address_parser_context ctx;
@@ -1105,13 +1334,17 @@
}
ctx.str = str_new(128);
- ctx.fill_missing = fill_missing;
+ ctx.fill_missing = (flags & MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING) !=
0;
+ ctx.non_strict_dots = (flags & MESSAGE_ADDRESS_PARSE_FLAG_STRICT_DOTS)
== 0;
+ ctx.non_strict_dots_as_invalid = (flags &
MESSAGE_ADDRESS_PARSE_FLAG_NON_STRICT_DOTS_AS_INVALID) != 0;
(void)parse_address_list(&ctx, max_addresses);
str_free(&ctx.str);
str_free(&str);
+ rfc822_parser_deinit(&ctx.parser);
+
return ctx.first_addr;
}
@@ -1140,6 +1373,18 @@
str = str_new(128);
+#if 0
+ if (addr == NULL)
+ return;
+
+ /* <> path */
+ if (addr->mailbox == NULL && addr->domain == NULL) {
+ i_assert(addr->next == NULL);
+ str_append(str, "<>");
+ return;
+ }
+#endif
+
/* a) mailbox@domain
b) name <@route:mailbox@domain>
c) group: .. ; */
@@ -1278,6 +1523,8 @@
ctx.str = str_new(128);
ctx.fill_missing = false;
+ ctx.non_strict_dots = false;
+ ctx.non_strict_dots_as_invalid = false;
ret = rfc822_skip_lwsp(&ctx.parser);
@@ -1286,6 +1533,9 @@
else
ret = -1;
+ if (ret >= 0)
+ ret = rfc822_skip_lwsp(&ctx.parser);
+
if (ret < 0 || ctx.parser.data != ctx.parser.end ||
ctx.addr.invalid_syntax) {
free(ctx.addr.mailbox);
free(ctx.addr.domain);
@@ -1305,6 +1555,8 @@
free(ctx.addr.name);
free(ctx.addr.original);
+ rfc822_parser_deinit(&ctx.parser);
+
str_free(&ctx.str);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/dovecot-parser.h
new/Email-Address-XS-1.05/dovecot-parser.h
--- old/Email-Address-XS-1.04/dovecot-parser.h 2018-06-09 18:23:51.000000000
+0200
+++ new/Email-Address-XS-1.05/dovecot-parser.h 2022-08-07 15:31:30.000000000
+0200
@@ -3,6 +3,20 @@
#include <stdbool.h>
+enum message_address_parse_flags {
+ /* If enabled, missing mailbox and domain are set to MISSING_MAILBOX
+ and MISSING_DOMAIN strings. Otherwise they're set to "". */
+ MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING = (1 << 0),
+ /* Require local-part to strictly adhere to RFC5322 when parsing dots.
+ For example ".user", "us..ser" and "user." will be invalid. This
+ isn't enabled by default, because these kind of invalid addresses
+ are commonly used in Japan. */
+ MESSAGE_ADDRESS_PARSE_FLAG_STRICT_DOTS = (1 << 1),
+ /* Same as MESSAGE_ADDRESS_PARSE_FLAG_STRICT_DOTS, but accept also
+ non-strict input. Flag invalid_syntax will be set to true. */
+ MESSAGE_ADDRESS_PARSE_FLAG_NON_STRICT_DOTS_AS_INVALID = (1 << 2),
+};
+
/* group: ... ; will be stored like:
{name = NULL, NULL, "group", NULL}, ..., {NULL, NULL, NULL, NULL}
*/
@@ -28,14 +42,10 @@
bool invalid_syntax;
};
-/* Parse message addresses from given data. If fill_missing is TRUE, missing
- mailbox and domain are set to MISSING_MAILBOX and MISSING_DOMAIN strings.
- Otherwise they're set to "".
-
- Note that giving an empty string will return NULL since there are no
- addresses. */
+/* Parse message addresses from given data. Note that giving an empty string
+ will return NULL since there are no addresses. */
struct message_address *
-message_address_parse(const char *str, size_t len, unsigned int max_addresses,
bool fill_missing);
+message_address_parse(const char *str, size_t len, unsigned int max_addresses,
enum message_address_parse_flags flags);
void message_address_add(struct message_address **first, struct
message_address **last,
const char *name, size_t name_len, const char *route,
size_t route_len,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/lib/Email/Address/XS.pm
new/Email-Address-XS-1.05/lib/Email/Address/XS.pm
--- old/Email-Address-XS-1.04/lib/Email/Address/XS.pm 2018-06-09
18:24:00.000000000 +0200
+++ new/Email-Address-XS-1.05/lib/Email/Address/XS.pm 2022-08-07
15:31:30.000000000 +0200
@@ -6,7 +6,7 @@
use strict;
use warnings;
-our $VERSION = '1.04';
+our $VERSION = '1.05';
use Carp;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Email-Address-XS-1.04/t/Email-Address-XS.t
new/Email-Address-XS-1.05/t/Email-Address-XS.t
--- old/Email-Address-XS-1.04/t/Email-Address-XS.t 2018-06-09
18:24:00.000000000 +0200
+++ new/Email-Address-XS-1.05/t/Email-Address-XS.t 2022-08-07
15:31:30.000000000 +0200
@@ -19,7 +19,7 @@
$Carp::Internal{'Test::Builder'} = 1;
$Carp::Internal{'Test::More'} = 1;
-use Test::More tests => 511;
+use Test::More tests => 516;
use Test::Builder;
local $SIG{__WARN__} = sub {
@@ -698,6 +698,16 @@
is($address->address(), '"winston.smith."@recdep.minitrue',
$subtest);
}
+ {
+ my $subtest = 'test method parse() in scalar context with valid
address followed by garbage';
+ my $address =
Email::Address::XS->parse('[email protected] garbage');
+ ok(!$address->is_valid(), $subtest);
+ is($address->original(), '[email protected] ',
$subtest);
+ is($address->user(), 'winston.smith', $subtest);
+ is($address->host(), 'recdep.minitrue', $subtest);
+ is($address->address(), '[email protected]',
$subtest);
+ }
+
}
#########################
++++++ cpanspec.yml ++++++
---
#description_paragraphs: 3
#description: |-
# override description from CPAN
#summary: override summary from CPAN
#no_testing: broken upstream
#sources:
# - source1
# - source2
#patches:
# foo.patch: -p1
# bar.patch:
# baz.patch: PATCH-FIX-OPENSUSE
#preamble: |-
# BuildRequires: gcc-c++
#post_prep: |-
# hunspell=`pkg-config --libs hunspell | sed -e 's,-l,,; s, *,,g'`
# sed -i -e "s,hunspell-X,$hunspell," t/00-prereq.t Makefile.PL
#post_build: |-
# rm unused.files
#post_install: |-
# sed on %{name}.files
#license: SUSE-NonFree
#skip_noarch: 1
#custom_build: |-
#./Build build flags=%{?_smp_mflags} --myflag
#custom_test: |-
#startserver && make test
#ignore_requires: Bizarre::Module
#skip_doc: regexp_to_skip_for_doc.*
#add_doc: files to add to docs
#misc: |-
#anything else to be added to spec file
#follows directly after %files section, so it can contain new blocks or also
#changes to %files section