summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2017-07-05 14:34:13 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2017-07-05 14:34:13 (GMT)
commit57e392b38ccf9132f6e5640766825e71a2397819 (patch) (side-by-side diff)
treead7cbca84dc7ee0c4e59eb996dd9375f71119a9c
parent9dfd5bfbeb2af9142c11d4a0f9ed94ac44726268 (diff)
downloadmailutils-57e392b38ccf9132f6e5640766825e71a2397819.tar.gz
mailutils-57e392b38ccf9132f6e5640766825e71a2397819.tar.bz2
MH: Rewrite the mymbox function.
* mh/mh_init.c (emailcmp): Rewrite. (email_match): New function. (mh_is_my_name): Cache Alternate-Mailboxes and mh_my_email in a static mu_address_t; use email_match to compare. * mh/tests/fmtfunc.at: Test mymbox function.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--mh/mh_init.c235
-rw-r--r--mh/tests/fmtfunc.at26
2 files changed, 209 insertions, 52 deletions
diff --git a/mh/mh_init.c b/mh/mh_init.c
index 23f5e20..3cc3625 100644
--- a/mh/mh_init.c
+++ b/mh/mh_init.c
@@ -91,74 +91,207 @@ mh_my_email (void)
}
return my_email;
}
+
+enum part_match_mode
+ {
+ part_match_local,
+ part_match_domain
+ };
+
+enum part_match_result
+ {
+ part_match_false,
+ part_match_true,
+ part_match_abort
+ };
+
+static int match_char_class (char const **pexpr, char c, int icase);
+
+static enum part_match_result
+part_match (char const *expr, char const *name, enum part_match_mode mode)
+{
+ int c;
-int
-emailcmp (char *pattern, char *name)
+ while (*expr)
+ {
+ if (*name == 0 && *expr != '*')
+ return part_match_abort;
+ switch (*expr)
+ {
+ case '*':
+ while (*++expr == '*')
+ ;
+ if (*expr == 0)
+ return part_match_true;
+ while (*name)
+ {
+ int res = part_match (expr, name++, mode);
+ if (res != part_match_false)
+ return res;
+ }
+ return part_match_abort;
+
+ case '?':
+ expr++;
+ if (*name == 0)
+ return part_match_false;
+ name++;
+ break;
+
+ case '[':
+ if (!match_char_class (&expr, *name, mode == part_match_domain))
+ return part_match_false;
+ name++;
+ break;
+
+ case '\\':
+ if (expr[1])
+ {
+ c = *++expr; expr++;
+ if (*name != mu_wordsplit_c_unquote_char (c))
+ return part_match_false;
+ name++;
+ break;
+ }
+ /* fall through */
+
+ default:
+ if (mode == part_match_local)
+ {
+ if (*expr != *name)
+ return part_match_false;
+ if ('@' == *name)
+ mode = part_match_domain;
+ }
+ else
+ {
+ if (mu_tolower (*expr) != mu_tolower (*name))
+ return part_match_false;
+ }
+ expr++;
+ name++;
+ }
+ }
+
+ if (*name == 0)
+ return part_match_true;
+
+ if (mode == part_match_local && *name == '@')
+ return part_match_true;
+
+ return part_match_false;
+}
+
+static int
+match_char_class (char const **pexpr, char c, int icase)
{
- char *p;
+ int res;
+ int rc;
+ char const *expr = *pexpr;
- p = strchr (pattern, '@');
- if (p)
- for (p++; *p; p++)
- *p = mu_toupper (*p);
+ if (icase)
+ c = mu_toupper (c);
+
+ expr++;
+ if (*expr == '^')
+ {
+ res = 0;
+ expr++;
+ }
+ else
+ res = 1;
+
+ if (*expr == '-' || *expr == ']')
+ rc = c == *expr++;
+ else
+ rc = !res;
+
+ for (; *expr && *expr != ']'; expr++)
+ {
+ if (rc == res)
+ {
+ if (*expr == '\\' && expr[1] == ']')
+ expr++;
+ }
+ else if (expr[1] == '-')
+ {
+ if (*expr == '\\')
+ rc = *++expr == c;
+ else
+ {
+ if (icase)
+ rc = mu_toupper (*expr) <= c && c <= mu_toupper (expr[2]);
+ else
+ rc = *expr <= c && c <= expr[2];
+ expr += 2;
+ }
+ }
+ else if (*expr == '\\' && expr[1] == ']')
+ rc = *++expr == c;
+ else if (icase)
+ rc = mu_toupper(*expr) == c;
+ else
+ rc = *expr == c;
+ }
+ *pexpr = *expr ? expr + 1 : expr;
+ return rc == res;
+}
- return fnmatch (pattern, name, 0);
+static int
+email_match (char const *pattern, char const *name)
+{
+ return part_match (pattern, name, part_match_local) == part_match_true;
}
int
mh_is_my_name (const char *name)
{
- char *pname, *p;
- int rc = 0;
-
- pname = mu_strdup (name);
- p = strchr (pname, '@');
- if (p)
- for (p++; *p; p++)
- *p = mu_toupper (*p);
+ static mu_address_t addr;
+ mu_address_t p;
- if (emailcmp (mh_my_email (), pname) == 0)
- rc = 1;
- else
+ if (!addr)
{
- const char *nlist = mh_global_profile_get ("Alternate-Mailboxes", NULL);
+ const char *nlist;
+ int rc;
+
+ rc = mu_address_create (&addr, mh_my_email ());
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_address_create", mh_my_email (),
+ rc);
+ return 0;
+ }
+
+ nlist = mh_global_profile_get ("Alternate-Mailboxes", NULL);
if (nlist)
{
- const char *end, *p;
- char *pat;
- int len;
-
- for (p = nlist; rc == 0 && *p; p = end)
+ mu_address_t tmp;
+ struct mu_address hint;
+
+ hint.domain = NULL;
+ rc = mu_address_create_hint (&tmp, nlist, &hint,
+ MU_ADDR_HINT_DOMAIN);
+ if (rc == 0)
{
-
- while (*p && mu_isspace (*p))
- p++;
-
- end = strchr (p, ',');
- if (end)
- {
- len = end - p;
- end++;
- }
- else
- {
- len = strlen (p);
- end = p + len;
- }
-
- while (len > 0 && mu_isspace (p[len-1]))
- len--;
-
- pat = mu_alloc (len + 1);
- memcpy (pat, p, len);
- pat[len] = 0;
- rc = emailcmp (pat, pname) == 0;
- free (pat);
+ rc = mu_address_union (&addr, tmp);
+ if (rc)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_address_union", NULL, rc);
+ mu_address_destroy (&tmp);
+ }
+ else
+ {
+ mu_error (_("bad Alternate-Mailboxes: %s; please fix"),
+ mu_strerror (rc));
}
}
}
- free (pname);
- return rc;
+
+ for (p = addr; p; p = p->next)
+ {
+ if (email_match (p->email, name))
+ return 1;
+ }
+ return 0;
}
static int
diff --git a/mh/tests/fmtfunc.at b/mh/tests/fmtfunc.at
index bb81f8a..b8eb66a 100644
--- a/mh/tests/fmtfunc.at
+++ b/mh/tests/fmtfunc.at
@@ -650,7 +650,31 @@ FMTFUNC([mbox],
[gray
])
-# FIXME: mymbox
+AT_SETUP([mymbox])
+AT_KEYWORDS([fmtfunc format])
+AT_DATA([mh_profile],[Charset: auto
+Local-Mailbox: mu@example.net
+Alternate-Mailboxes: gray, *@mailutils.*
+])
+AT_DATA([message],[From: mu@example.net
+X-From-1: gray@localhost
+X-From-2: root@mailutils.org
+X-From-3: mu@example.com
+])
+AT_DATA([input.fmt],[%(mymbox{From})
+%(mymbox{X-From-1})
+%(mymbox{X-From-2})
+%(mymbox{X-From-3})
+])
+AT_CHECK([MH=`pwd`/mh_profile fmtcheck -form input.fmt -msgno 1 -width 80 message
+],
+[0],
+[1
+1
+1
+0
+])
+AT_CLEANUP
FMTFUNC([host],
[%(host{From})

Return to:

Send suggestions and report system problems to the System administrator.