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