On Thu, 2005-04-28 at 16:31 +0000, Aaron Stone wrote: > On Thu, Apr 28, 2005, Geo Carncross <[EMAIL PROTECTED]> > said: > > > 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. > > Awesome variable names. What the hell does this do?
What's wrong with 'em? It works like fnmatch(), only instead of shell-wildcards, it understands IMAP wildcards: * - zero or more of anything % - like *, but stops at level-separator p=pattern s=string to search x=separator string ("." or "/"- multichar okay; e.g. "π" would work if you can find a IMAP client that read rfc2060) flags = presently only LISTEX_NOCASE -- if you want case-insensitive "folders" Presently, dbmail uses "/" (IIRC), but namespace support in the future might change that. Better start early. defining -DTEST allowed me to quickly exercise it. I didn't double-check rfc2060 while doing it, but while my memory isn't infallible, I think it's pretty important to get this on trunk and drop the nasty regex code. Oh, although I wasn't completely clear on this: listex.c is hereby released under the GNU Public License V2. The new attach supports UTF8 correctly on patterns, and correctly matches multibyte separators.. It also correctly implements LISTEX_NOCASE -- Internet Connection High Quality Web Hosting http://www.internetconnection.net/
/* listexpression match for imap (rfc2060) */ #include <ctype.h> #define LISTEX_NOCASE 1 int listex_match(const char *p, const char *s, const char *x, int flags) { int i, p8; p8=0; while (*p) { if (!p8 && *p == '%') { p++; while (*s) { for (i = 0; x[i] && x[i] == s[i]; i++); if (! x[i]) { s += i; break; } s++; } /* %. */ for (i = 0; x[i] && x[i] == p[i]; i++); if (! x[i]) p += i; if (*s || *p) return 0; return 1; } if (!p8 && *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 (!p8 && *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 && tolower(((unsigned int)*p)) == tolower(((unsigned int)*s))) || (*p == *s)) { p8=(((unsigned char)*p) > 0xC0); 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)) #define N(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"); N(0, "INBOX\317\200*Bar", "INBOX"); N(0, "INBOX\317\200*Bar", "INBOX\317\200""Foo"); N(1, "INBOX\317\200*Bar", "INBOX\317\200""Foo\317\200""Bar"); } #endif