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


Reply via email to