author | Sergey Poznyakoff <gray@gnu.org> | 2017-07-05 14:34:13 (GMT) |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2017-07-05 14:34:13 (GMT) |
commit | 57e392b38ccf9132f6e5640766825e71a2397819 (patch) (unidiff) | |
tree | ad7cbca84dc7ee0c4e59eb996dd9375f71119a9c | |
parent | 9dfd5bfbeb2af9142c11d4a0f9ed94ac44726268 (diff) | |
download | mailutils-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.
-rw-r--r-- | mh/mh_init.c | 235 | ||||
-rw-r--r-- | mh/tests/fmtfunc.at | 26 |
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 | |||
95 | enum part_match_mode | ||
96 | { | ||
97 | part_match_local, | ||
98 | part_match_domain | ||
99 | }; | ||
100 | |||
101 | enum part_match_result | ||
102 | { | ||
103 | part_match_false, | ||
104 | part_match_true, | ||
105 | part_match_abort | ||
106 | }; | ||
107 | |||
108 | static int match_char_class (char const **pexpr, char c, int icase); | ||
109 | |||
110 | static enum part_match_result | ||
111 | part_match (char const *expr, char const *name, enum part_match_mode mode) | ||
112 | { | ||
113 | int c; | ||
94 | 114 | ||
95 | int | 115 | while (*expr) |
96 | emailcmp (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 | |||
185 | static int | ||
186 | match_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); | 240 | static int |
241 | email_match (char const *pattern, char const *name) | ||
242 | { | ||
243 | return part_match (pattern, name, part_match_local) == part_match_true; | ||
106 | } | 244 | } |
107 | 245 | ||
108 | int | 246 | int |
109 | mh_is_my_name (const char *name) | 247 | mh_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 | ||
164 | static int | 297 | 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], | |||
650 | [gray | 650 | [gray |
651 | ]) | 651 | ]) |
652 | 652 | ||
653 | # FIXME: mymbox | 653 | AT_SETUP([mymbox]) |
654 | AT_KEYWORDS([fmtfunc format]) | ||
655 | AT_DATA([mh_profile],[Charset: auto | ||
656 | Local-Mailbox: mu@example.net | ||
657 | Alternate-Mailboxes: gray, *@mailutils.* | ||
658 | ]) | ||
659 | AT_DATA([message],[From: mu@example.net | ||
660 | X-From-1: gray@localhost | ||
661 | X-From-2: root@mailutils.org | ||
662 | X-From-3: mu@example.com | ||
663 | ]) | ||
664 | AT_DATA([input.fmt],[%(mymbox{From}) | ||
665 | %(mymbox{X-From-1}) | ||
666 | %(mymbox{X-From-2}) | ||
667 | %(mymbox{X-From-3}) | ||
668 | ]) | ||
669 | AT_CHECK([MH=`pwd`/mh_profile fmtcheck -form input.fmt -msgno 1 -width 80 message | ||
670 | ], | ||
671 | [0], | ||
672 | [1 | ||
673 | 1 | ||
674 | 1 | ||
675 | 0 | ||
676 | ]) | ||
677 | AT_CLEANUP | ||
654 | 678 | ||
655 | FMTFUNC([host], | 679 | FMTFUNC([host], |
656 | [%(host{From}) | 680 | [%(host{From}) |