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) (unidiff)
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)
91 } 91 }
92 return my_email; 92 return my_email;
93} 93}
94
95enum part_match_mode
96 {
97 part_match_local,
98 part_match_domain
99 };
100
101enum part_match_result
102 {
103 part_match_false,
104 part_match_true,
105 part_match_abort
106 };
107
108static int match_char_class (char const **pexpr, char c, int icase);
109
110static enum part_match_result
111part_match (char const *expr, char const *name, enum part_match_mode mode)
112{
113 int c;
94 114
95int 115 while (*expr)
96emailcmp (char *pattern, char *name) 116 {
117 if (*name == 0 && *expr != '*')
118 return part_match_abort;
119 switch (*expr)
120 {
121 case '*':
122 while (*++expr == '*')
123 ;
124 if (*expr == 0)
125 return part_match_true;
126 while (*name)
127 {
128 int res = part_match (expr, name++, mode);
129 if (res != part_match_false)
130 return res;
131 }
132 return part_match_abort;
133
134 case '?':
135 expr++;
136 if (*name == 0)
137 return part_match_false;
138 name++;
139 break;
140
141 case '[':
142 if (!match_char_class (&expr, *name, mode == part_match_domain))
143 return part_match_false;
144 name++;
145 break;
146
147 case '\\':
148 if (expr[1])
149 {
150 c = *++expr; expr++;
151 if (*name != mu_wordsplit_c_unquote_char (c))
152 return part_match_false;
153 name++;
154 break;
155 }
156 /* fall through */
157
158 default:
159 if (mode == part_match_local)
160 {
161 if (*expr != *name)
162 return part_match_false;
163 if ('@' == *name)
164 mode = part_match_domain;
165 }
166 else
167 {
168 if (mu_tolower (*expr) != mu_tolower (*name))
169 return part_match_false;
170 }
171 expr++;
172 name++;
173 }
174 }
175
176 if (*name == 0)
177 return part_match_true;
178
179 if (mode == part_match_local && *name == '@')
180 return part_match_true;
181
182 return part_match_false;
183}
184
185static int
186match_char_class (char const **pexpr, char c, int icase)
97{ 187{
98 char *p; 188 int res;
189 int rc;
190 char const *expr = *pexpr;
99 191
100 p = strchr (pattern, '@'); 192 if (icase)
101 if (p) 193 c = mu_toupper (c);
102 for (p++; *p; p++) 194
103 *p = mu_toupper (*p); 195 expr++;
196 if (*expr == '^')
197 {
198 res = 0;
199 expr++;
200 }
201 else
202 res = 1;
203
204 if (*expr == '-' || *expr == ']')
205 rc = c == *expr++;
206 else
207 rc = !res;
208
209 for (; *expr && *expr != ']'; expr++)
210 {
211 if (rc == res)
212 {
213 if (*expr == '\\' && expr[1] == ']')
214 expr++;
215 }
216 else if (expr[1] == '-')
217 {
218 if (*expr == '\\')
219 rc = *++expr == c;
220 else
221 {
222 if (icase)
223 rc = mu_toupper (*expr) <= c && c <= mu_toupper (expr[2]);
224 else
225 rc = *expr <= c && c <= expr[2];
226 expr += 2;
227 }
228 }
229 else if (*expr == '\\' && expr[1] == ']')
230 rc = *++expr == c;
231 else if (icase)
232 rc = mu_toupper(*expr) == c;
233 else
234 rc = *expr == c;
235 }
236 *pexpr = *expr ? expr + 1 : expr;
237 return rc == res;
238}
104 239
105 return fnmatch (pattern, name, 0); 240static int
241email_match (char const *pattern, char const *name)
242{
243 return part_match (pattern, name, part_match_local) == part_match_true;
106} 244}
107 245
108int 246int
109mh_is_my_name (const char *name) 247mh_is_my_name (const char *name)
110{ 248{
111 char *pname, *p; 249 static mu_address_t addr;
112 int rc = 0; 250 mu_address_t p;
113
114 pname = mu_strdup (name);
115 p = strchr (pname, '@');
116 if (p)
117 for (p++; *p; p++)
118 *p = mu_toupper (*p);
119 251
120 if (emailcmp (mh_my_email (), pname) == 0) 252 if (!addr)
121 rc = 1;
122 else
123 { 253 {
124 const char *nlist = mh_global_profile_get ("Alternate-Mailboxes", NULL); 254 const char *nlist;
255 int rc;
256
257 rc = mu_address_create (&addr, mh_my_email ());
258 if (rc)
259 {
260 mu_diag_funcall (MU_DIAG_ERROR, "mu_address_create", mh_my_email (),
261 rc);
262 return 0;
263 }
264
265 nlist = mh_global_profile_get ("Alternate-Mailboxes", NULL);
125 if (nlist) 266 if (nlist)
126 { 267 {
127 const char *end, *p; 268 mu_address_t tmp;
128 char *pat; 269 struct mu_address hint;
129 int len; 270
130 271 hint.domain = NULL;
131 for (p = nlist; rc == 0 && *p; p = end) 272 rc = mu_address_create_hint (&tmp, nlist, &hint,
273 MU_ADDR_HINT_DOMAIN);
274 if (rc == 0)
132 { 275 {
133 276 rc = mu_address_union (&addr, tmp);
134 while (*p && mu_isspace (*p)) 277 if (rc)
135 p++; 278 mu_diag_funcall (MU_DIAG_ERROR, "mu_address_union", NULL, rc);
136 279 mu_address_destroy (&tmp);
137 end = strchr (p, ','); 280 }
138 if (end) 281 else
139 { 282 {
140 len = end - p; 283 mu_error (_("bad Alternate-Mailboxes: %s; please fix"),
141 end++; 284 mu_strerror (rc));
142 }
143 else
144 {
145 len = strlen (p);
146 end = p + len;
147 }
148
149 while (len > 0 && mu_isspace (p[len-1]))
150 len--;
151
152 pat = mu_alloc (len + 1);
153 memcpy (pat, p, len);
154 pat[len] = 0;
155 rc = emailcmp (pat, pname) == 0;
156 free (pat);
157 } 285 }
158 } 286 }
159 } 287 }
160 free (pname); 288
161 return rc; 289 for (p = addr; p; p = p->next)
290 {
291 if (email_match (p->email, name))
292 return 1;
293 }
294 return 0;
162} 295}
163 296
164static int 297static 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],
650[gray 650[gray
651]) 651])
652 652
653# FIXME: mymbox 653AT_SETUP([mymbox])
654AT_KEYWORDS([fmtfunc format])
655AT_DATA([mh_profile],[Charset: auto
656Local-Mailbox: mu@example.net
657Alternate-Mailboxes: gray, *@mailutils.*
658])
659AT_DATA([message],[From: mu@example.net
660X-From-1: gray@localhost
661X-From-2: root@mailutils.org
662X-From-3: mu@example.com
663])
664AT_DATA([input.fmt],[%(mymbox{From})
665%(mymbox{X-From-1})
666%(mymbox{X-From-2})
667%(mymbox{X-From-3})
668])
669AT_CHECK([MH=`pwd`/mh_profile fmtcheck -form input.fmt -msgno 1 -width 80 message
670],
671[0],
672[1
6731
6741
6750
676])
677AT_CLEANUP
654 678
655FMTFUNC([host], 679FMTFUNC([host],
656[%(host{From}) 680[%(host{From})

Return to:

Send suggestions and report system problems to the System administrator.