On Thu, 2005-04-28 at 09:07 +0200, Paul J Stevens wrote:
> >>Currently the *only* place that uses (posix) regex is the namespace code in
> >>imap. I just finished a working implementation of base-subject retrieval
> >>using
> >>pcre, but that's not in svn yet.
> >
> >
> > Why do we need regex for namespaces? The server defines the namespaces,
> > and they're all fixed-strings... aren't they?
>
> I checked. _ic_list in imapcommands.c uses regex to find mailboxes bases
> on regexes by translating the LIST command to regex patterns.
Try the attached; I just whipped it up as a imap-style fnmatch()
It's not optimal: the *-sync shouldn't be recursive,
but I think it's pretty close to correct.
It has a test-harness, so if we find something it _DOESNT_ work on, it
can always be added.
--
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/
/* listexpression match for imap (rfc2060) */
#define LISTEX_NOCASE 1
int listex_match(const char *p, const char *s,
const char *x, int flags)
{
int i;
while (*p) {
if (*p == '%') {
while (*s && *s != *x) s++;
p++;
for (i = 0; x[i] && p[i] == x[i] && p[i] == s[i]; i++);
if (! x[i]) {
p += i; s += i;
continue; /* sync'd */
}
if (s[i] || p[i]) return 0;
return 1;
}
if (*p == '*') {
/* use recursive for synchronize */
p++;
if (!(*p)) return 1;
while (*s) {
if (listex_match(p,s,x,flags)) return 1;
s++;
}
return 0;
}
if (*p == *x) {
for (i = 0; x[i] && p[i] == x[i] && p[i] == s[i]; i++);
if (! x[i]) {
p += i; s += i;
continue; /* sync'd */
}
/* fall; try regular search */
}
if (flags & LISTEX_NOCASE && *p == *s) {
p++; s++;
} else if (*p == *s) {
p++; s++;
} else {
/* failed */
return 0;
}
}
if (*p || *s) return 0;
return 1;
}
#ifdef TEST
#include <stdio.h>
int main(int argc, char *argv[])
{
#define Y(z,q) if(z!=(q)) {fprintf(stderr,"Failed: %d != %s\n",z,#q);exit(1);}
#define X(z,a,b) Y(z,listex_match(a,b,".",0))
X(1, "INBOX", "INBOX");
X(0, "INBOX", "INBOX.Foo");
X(0, "INBOX", "INBOX.Foo.Bar");
X(0, "INBOX.%", "INBOX");
X(1, "INBOX.%", "INBOX.Foo");
X(0, "INBOX.%", "INBOX.Foo.Bar");
X(0, "INBOX.*", "INBOX");
X(1, "INBOX.*", "INBOX.Foo");
X(1, "INBOX.*", "INBOX.Foo.Bar");
X(1, "INBOX*", "INBOX");
X(1, "INBOX*", "INBOX.Foo");
X(1, "INBOX*", "INBOX.Foo.Bar");
X(1, "INBOX%", "INBOX");
X(0, "INBOX%", "INBOX.Foo");
X(0, "INBOX%", "INBOX.Foo.Bar");
X(0, "INBOX*Foo", "INBOX");
X(1, "INBOX*Foo", "INBOX.Foo");
X(0, "INBOX*Foo", "INBOX.Foo.Bar");
X(0, "INBOX*Bar", "INBOX");
X(0, "INBOX*Bar", "INBOX.Foo");
X(1, "INBOX*Bar", "INBOX.Foo.Bar");
X(0, "INBOX.*Bar", "INBOX");
X(0, "INBOX.*Bar", "INBOX.Foo");
X(1, "INBOX.*Bar", "INBOX.Foo.Bar");
}
#endif