diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 |
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 |
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /imap/mailboxlist.c | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'imap/mailboxlist.c')
| -rw-r--r-- | imap/mailboxlist.c | 1064 |
1 files changed, 1064 insertions, 0 deletions
diff --git a/imap/mailboxlist.c b/imap/mailboxlist.c new file mode 100644 index 0000000..a204ebf --- /dev/null +++ b/imap/mailboxlist.c @@ -0,0 +1,1064 @@ +/* +** Copyright 1998 - 2007 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <fcntl.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_DIRENT_H +#include <dirent.h> +#define NAMLEN(dirent) strlen((dirent)->d_name) +#else +#define dirent direct +#define NAMLEN(dirent) (dirent)->d_namlen +#if HAVE_SYS_NDIR_H +#include <sys/ndir.h> +#endif +#if HAVE_SYS_DIR_H +#include <sys/dir.h> +#endif +#if HAVE_NDIR_H +#include <ndir.h> +#endif +#endif +#if HAVE_UTIME_H +#include <utime.h> +#endif +#if TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#else +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#else +#include <time.h> +#endif +#endif + +#include <sys/types.h> +#include <sys/stat.h> + +#include "imaptoken.h" +#include "imapwrite.h" +#include "imapscanclient.h" + +#include "mysignal.h" +#include "imapd.h" +#include "fetchinfo.h" +#include "searchinfo.h" +#include "storeinfo.h" +#include "mailboxlist.h" + +#include "maildir/config.h" +#include "maildir/maildirmisc.h" +#include "maildir/maildiraclt.h" +#include "maildir/maildirnewshared.h" +#include "maildir/maildirinfo.h" +#include "unicode/unicode.h" +#include "courierauth.h" + + +static const char hierchs[]={HIERCH, 0}; + +extern char *decode_valid_mailbox(const char *, int); +extern dev_t homedir_dev; +extern ino_t homedir_ino; +/* + LIST MAILBOXES +*/ + +static int do_mailbox_list(int do_lsub, char *qq, int isnullname, + int (*callback_func)(const char *hiersep, + const char *mailbox, + int flags, + void *void_arg), + void *void_arg); + +static int shared_index_err_reported=0; + +const char *maildir_shared_index_file() +{ + static char *filenamep=NULL; + + if (filenamep == NULL) + { + const char *p=getenv("IMAP_SHAREDINDEXFILE"); + + if (p && *p) + { + const char *q=auth_getoptionenv("sharedgroup"); + + if (!q) q=""; + + filenamep=malloc(strlen(p)+strlen(q)+1); + + if (!filenamep) + write_error_exit(0); + + strcat(strcpy(filenamep, p), q); + } + } + + if (filenamep && !shared_index_err_reported) /* Bitch just once */ + { + struct stat stat_buf; + + shared_index_err_reported=1; + if (stat(filenamep, &stat_buf)) + { + fprintf(stderr, "ERR: "); + perror(filenamep); + } + } + + return filenamep; +} + +/* +** IMAP sucks. Here's why. +*/ + + +int mailbox_scan(const char *reference, const char *name, + int list_options, + int (*callback_func)(const char *hiersep, + const char *mailbox, + int flags, + void *void_arg), + void *void_arg) +{ + char *pattern, *p; + int nullname= *name == 0; + int rc; + + pattern=malloc(strlen(reference)+strlen(name)+2); + + strcpy(pattern, reference); + + p=strrchr(pattern, HIERCH); + if (p && p[1] == 0) *p=0; /* Strip trailing . for now */ + if (*pattern) + { + struct maildir_info mi; + + if (maildir_info_imap_find(&mi, pattern, + getenv("AUTHENTICATED"))) + { + free(pattern); + return (0); /* Invalid reference */ + } + maildir_info_destroy(&mi); + } + + /* Combine reference and name. */ + if (*pattern && *name) + strcat(pattern, hierchs); + strcat(pattern, name); + + if (name && *name) + { + char *s=strrchr(pattern, HIERCH); + + if (s && s[1] == 0) *s=0; /* strip trailing . */ + + } + + /* Now, do the list */ + + rc=do_mailbox_list(list_options, pattern, nullname, + callback_func, void_arg); + free(pattern); + return (rc); +} + +static int match_mailbox(char *, char *, int flags); +static void match_mailbox_prep(char *); + +/* Check if a folder has any new messages */ + +static int hasnewmsgs2(const char *dir) +{ +DIR *dirp=opendir(dir); +struct dirent *de; + + while (dirp && (de=readdir(dirp)) != 0) + { + char *p; + + if (de->d_name[0] == '.') continue; + p=strrchr(de->d_name, MDIRSEP[0]); + if (p == 0 || strncmp(p, MDIRSEP "2,", 3) || + strchr(p, 'S') == 0) + { + closedir(dirp); + return (1); + } + } + if (dirp) closedir(dirp); + return (0); +} + +static int hasnewmsgs(const char *folder) +{ +char *dir=decode_valid_mailbox(folder, 0); +char *subdir; + + if (!dir) return (0); + + if (is_sharedsubdir(dir)) + maildir_shared_sync(dir); + + subdir=malloc(strlen(dir)+sizeof("/cur")); + if (!subdir) write_error_exit(0); + strcat(strcpy(subdir, dir), "/new"); + if (hasnewmsgs2(subdir)) + { + free(subdir); + free(dir); + return (1); + } + + strcat(strcpy(subdir, dir), "/cur"); + if (hasnewmsgs2(subdir)) + { + free(subdir); + free(dir); + return (1); + } + + free(subdir); + free(dir); + return (0); +} + +/* Each folder is listed with the \Noinferiors tag. Then, for every subfolder +** we've seen, we need to output a listing for all the higher-level hierarchies +** with a \Noselect tag. Therefore, we need to keep track of all the +** hierarchies we've seen so far. +*/ + +struct hierlist { + struct hierlist *next; + int flag; + char *hier; + } ; + +static int add_hier(struct hierlist **h, const char *s) +{ +struct hierlist *p; + + for (p= *h; p; p=p->next) + if (strcmp(p->hier, s) == 0) return (1); + /* Seen this one already */ + + if ((p=(struct hierlist *) + malloc( sizeof(struct hierlist)+1+strlen(s))) == 0) + /* HACK!!!! */ + write_error_exit(0); + p->flag=0; + p->hier=(char *)(p+1); + strcpy(p->hier, s); + p->next= *h; + *h=p; + return (0); +} + +static struct hierlist *search_hier(struct hierlist *h, const char *s) +{ +struct hierlist *p; + + for (p= h; p; p=p->next) + if (strcmp(p->hier, s) == 0) return (p); + return (0); +} + +static void hier_entry(char *folder, + struct hierlist **hierarchies); + +static int has_hier_entry(char *folder, + struct hierlist **hierarchies); + +static void folder_entry(char *folder, char *pattern, + int list_options, + struct hierlist **folders, + struct hierlist **hierarchies) +{ + size_t i; + size_t folder_l=strlen(folder); + + int need_add_hier; + int need_add_folders; + + match_mailbox_prep(folder); + + /* Optimize away folders we don't care about */ + + for (i=0; pattern[i]; i++) + { + if ((!(list_options & LIST_CHECK1FOLDER)) && + (pattern[i] == '%' || pattern[i] == '*')) + { + while (i) + { + if (pattern[i] == HIERCH) + break; + --i; + } + break; + } + } + + if (folder_l <= i) + { + if (memcmp(folder, pattern, folder_l)) + return; + + if (folder_l != i && pattern[folder_l] != HIERCH) + return; + } + else if (i) + { + if (memcmp(folder, pattern, i)) + return; + if (folder[i] != HIERCH) + return; + } + + need_add_folders=0; + + if (match_mailbox(folder, pattern, list_options) == 0) + need_add_folders=1; + + need_add_hier=0; + if (!has_hier_entry(folder, hierarchies)) + need_add_hier=1; + + if (!need_add_folders && !need_add_hier) + return; /* Nothing to do */ + + { + CHECK_RIGHTSM(folder, have_rights, ACL_LOOKUP); + + if (!have_rights[0]) + return; + } + + if (need_add_folders) + (void) add_hier(folders, folder); + + if (need_add_hier) + hier_entry(folder, hierarchies); +} + +static void hier_entry(char *folder, + struct hierlist **hierarchies) +{ + unsigned i; + + for (i=0; folder[i]; i++) + { + if (folder[i] != HIERCH) continue; + folder[i]=0; + (void)add_hier(hierarchies, folder); + folder[i]=HIERCH; + } +} + +static int has_hier_entry(char *folder, + struct hierlist **hierarchies) +{ + unsigned i; + + for (i=0; folder[i]; i++) + { + if (folder[i] != HIERCH) continue; + folder[i]=0; + if (!search_hier(*hierarchies, folder)) + { + folder[i]=HIERCH; + return (0); + } + folder[i]=HIERCH; + } + return (1); +} + +struct list_sharable_info { + char *pattern; + struct hierlist **folders, **hierarchies; + int flags; + int (*callback_func)(const char *hiersep, + const char *mailbox, + int flags, + void *void_arg); + void *cb_arg; + } ; + +static void list_sharable(const char *n, + void *voidp) +{ +struct list_sharable_info *ip=(struct list_sharable_info *)voidp; +char *p=malloc(strlen(n)+sizeof("shared.")); + + if (!p) write_error_exit(0); + + strcat(strcpy(p, "shared."), n); + + folder_entry(p, ip->pattern, ip->flags, + ip->folders, ip->hierarchies); + + free(p); +} + +static void list_subscribed(char *hier, + int flags, + struct hierlist **folders, + struct hierlist **hierarchies) +{ +char buf[BUFSIZ]; +FILE *fp; + + fp=fopen(SUBSCRIBEFILE, "r"); + if (fp) + { + while (fgets(buf, sizeof(buf), fp) != 0) + { + char *q=strchr(buf, '\n'); + + if (q) *q=0; + + if (*hier == '#') + { + if (*buf != '#') + continue; + } + else + { + if (*buf == '#') + continue; + } + + folder_entry(buf, hier, flags, + folders, hierarchies); + } + fclose(fp); + } +} + +static void maildir_scan(const char *inbox_dir, + const char *inbox_name, + struct list_sharable_info *shared_info) +{ + DIR *dirp; + struct dirent *de; + + /* Scan maildir, looking for .subdirectories */ + + dirp=opendir(inbox_dir && inbox_dir ? inbox_dir:"."); + while (dirp && (de=readdir(dirp)) != 0) + { + char *p; + + if (de->d_name[0] != '.' || + strcmp(de->d_name, "..") == 0) + continue; + + if ((p=malloc(strlen(de->d_name)+strlen(inbox_name)+10)) == 0) + /* A bit too much, that's OK */ + write_error_exit(0); + + strcpy(p, inbox_name); + + if (strcmp(de->d_name, ".")) + strcat(p, de->d_name); + + folder_entry(p, shared_info->pattern, shared_info->flags, + shared_info->folders, + shared_info->hierarchies); + free(p); + } + + if (dirp) closedir(dirp); +} + +/* List the #shared hierarchy */ + +struct list_newshared_info { + const char *acc_pfix; + const char *skipped_pattern; + struct list_sharable_info *shared_info; + struct maildir_shindex_cache *parentCache; + int dorecurse; +}; + +static int list_newshared_cb(struct maildir_newshared_enum_cb *cb); +static int list_newshared_skipcb(struct maildir_newshared_enum_cb *cb); +static int list_newshared_skiplevel(struct maildir_newshared_enum_cb *cb); + +static int list_newshared_shortcut(const char *skipped_pattern, + struct list_sharable_info *shared_info, + const char *current_namespace, + struct maildir_shindex_cache *parentCache, + const char *indexfile, + const char *subhierarchy); + +static int list_newshared(const char *skipped_pattern, + struct list_sharable_info *shared_info) +{ + return list_newshared_shortcut(skipped_pattern, shared_info, + NEWSHARED, + NULL, NULL, NULL); +} + +static int list_newshared_shortcut(const char *skipped_pattern, + struct list_sharable_info *shared_info, + const char *acc_pfix, + struct maildir_shindex_cache *parentCache, + const char *indexfile, + const char *subhierarchy) +{ + struct list_newshared_info lni; + int rc; + struct maildir_shindex_cache *curcache=NULL; + + lni.acc_pfix=acc_pfix; + lni.skipped_pattern=skipped_pattern; + lni.shared_info=shared_info; + lni.dorecurse=1; + + /* Try for some common optimization, to avoid expanding the + ** entire #shared hierarchy, taking advantage of the cache list. + */ + + for (;;) + { + const char *p; + size_t i; + char *q; + int eof; + + if (strcmp(skipped_pattern, "%") == 0) + { + lni.dorecurse=0; + break; + } + + if (strncmp(skipped_pattern, "%" HIERCHS, + sizeof("%" HIERCHS)-1) == 0) + { + curcache=maildir_shared_cache_read(parentCache, + indexfile, + subhierarchy); + if (!curcache) + return 0; + + lni.acc_pfix=acc_pfix; + lni.skipped_pattern=skipped_pattern + + sizeof("%" HIERCHS)-1; + lni.parentCache=curcache; + + for (i=0; i<curcache->nrecords; i++) + { + if (i == 0) + { + curcache->indexfile.startingpos=0; + rc=maildir_newshared_nextAt(&curcache->indexfile, + &eof, + list_newshared_skiplevel, + &lni); + } + else + rc=maildir_newshared_next(&curcache->indexfile, + &eof, + list_newshared_skiplevel, + &lni); + + if (rc || eof) + { + fprintf(stderr, "ERR:maildir_newshared_next failed: %s\n", + strerror(errno)); + break; + } + } + return 0; + } + + for (p=skipped_pattern; *p; p++) + if (*p == HIERCH || + ((lni.shared_info->flags & LIST_CHECK1FOLDER) == 0 + && (*p == '*' || *p == '%'))) + break; + + if (*p && *p != HIERCH) + break; + + curcache=maildir_shared_cache_read(parentCache, indexfile, + subhierarchy); + if (!curcache) + return 0; + + for (i=0; i < curcache->nrecords; i++) + { + char *n=maildir_info_imapmunge(curcache->records[i] + .name); + + if (!n) + write_error_exit(0); + + if (strlen(n) == p-skipped_pattern && + strncmp(n, skipped_pattern, p-skipped_pattern) == 0) + { + free(n); + break; + } + free(n); + } + + if (i >= curcache->nrecords) /* not found */ + return 0; + + if (*p) + ++p; + + + q=malloc(strlen(acc_pfix)+(p-skipped_pattern)+1); + if (!q) + { + write_error_exit(0); + } + strcpy(q, acc_pfix); + strncat(q, skipped_pattern, p-skipped_pattern); + + lni.acc_pfix=q; + lni.skipped_pattern=p; + lni.parentCache=curcache; + + curcache->indexfile.startingpos=curcache->records[i].offset; + + rc=maildir_newshared_nextAt(&curcache->indexfile, &eof, + list_newshared_skipcb, &lni); + free(q); + return rc; + + } + + if (!indexfile) + indexfile=maildir_shared_index_file(); + + rc=maildir_newshared_enum(indexfile, list_newshared_cb, &lni); + + return rc; +} + +static int list_newshared_cb(struct maildir_newshared_enum_cb *cb) +{ + const char *name=cb->name; + const char *homedir=cb->homedir; + const char *maildir=cb->maildir; + struct list_newshared_info *lni= + (struct list_newshared_info *)cb->cb_arg; + char *n=maildir_info_imapmunge(name); + int rc; + + if (!n) + write_error_exit(0); + + if (homedir == NULL) + { + struct list_newshared_info new_lni= *lni; + char *new_pfix=malloc(strlen(lni->acc_pfix)+ + strlen(n)+2); + if (!new_pfix) + write_error_exit(0); + + strcat(strcpy(new_pfix, lni->acc_pfix), n); + + free(n); + n=new_pfix; + new_lni.acc_pfix=n; + add_hier(lni->shared_info->hierarchies, n); + hier_entry(n, lni->shared_info->hierarchies); + strcat(n, hierchs); + rc=lni->dorecurse ? + maildir_newshared_enum(maildir, list_newshared_cb, + &new_lni):0; + } + else + { + char *new_pfix; + struct stat stat_buf; + + new_pfix=maildir_location(homedir, maildir); + + if (stat(new_pfix, &stat_buf) < 0 || + /* maildir inaccessible, perhaps another server? */ + + (stat_buf.st_dev == homedir_dev && + stat_buf.st_ino == homedir_ino)) + /* Exclude ourselves from the shared list */ + { + free(new_pfix); + free(n); + return 0; + } + free(new_pfix); + + new_pfix=malloc(strlen(lni->acc_pfix)+ + strlen(n)+1); + if (!new_pfix) + write_error_exit(0); + + strcat(strcpy(new_pfix, lni->acc_pfix), n); + + free(n); + n=new_pfix; + + new_pfix=malloc(strlen(homedir)+strlen(maildir)+2); + + if (!new_pfix) + write_error_exit(0); + + if (*maildir == '/') + strcpy(new_pfix, maildir); + else + strcat(strcat(strcpy(new_pfix, homedir), "/"), + maildir); + + /* if (lni->dorecurse) */ + + maildir_scan(new_pfix, n, lni->shared_info); +#if 0 + else + { + folder_entry(n, lni->shared_info->pattern, + lni->shared_info->flags, + lni->shared_info->folders, + lni->shared_info->hierarchies); + } +#endif + + free(new_pfix); + rc=0; + } + free(n); + return rc; +} + +static int list_newshared_skiplevel(struct maildir_newshared_enum_cb *cb) +{ + struct list_newshared_info *lni= + (struct list_newshared_info *)cb->cb_arg; + char *n=maildir_info_imapmunge(cb->name); + + char *p=malloc(strlen(lni->acc_pfix)+strlen(n)+sizeof(HIERCHS)); + int rc; + const char *save_skip; + + if (!n || !p) + write_error_exit(0); + + strcat(strcat(strcpy(p, lni->acc_pfix), n), HIERCHS); + free(n); + + save_skip=lni->acc_pfix; + lni->acc_pfix=p; + + rc=list_newshared_skipcb(cb); + lni->acc_pfix=save_skip; + free(p); + return rc; +} + +static int list_newshared_skipcb(struct maildir_newshared_enum_cb *cb) +{ + struct list_newshared_info *lni= + (struct list_newshared_info *)cb->cb_arg; + char *dir; + char *inbox_name; + + if (cb->homedir == NULL) + return list_newshared_shortcut(lni->skipped_pattern, + lni->shared_info, + lni->acc_pfix, + lni->parentCache, + cb->maildir, + cb->name); + + inbox_name=my_strdup(lni->acc_pfix); + + dir=strrchr(inbox_name, HIERCH); + if (dir && dir[1] == 0) + *dir=0; /* Strip trailing hier separator */ + + dir=malloc(strlen(cb->homedir)+strlen(cb->maildir)+2); + + if (!dir) + { + free(inbox_name); + write_error_exit(0); + } + + if (*cb->maildir == '/') + strcpy(dir, cb->maildir); + else + strcat(strcat(strcpy(dir, cb->homedir), "/"), cb->maildir); + + maildir_scan(dir, inbox_name, lni->shared_info); + free(dir); + free(inbox_name); + return 0; +} + +static int do_mailbox_list(int list_options, char *pattern, int isnullname, + int (*callback_func)(const char *hiersep, + const char *mailbox, + int flags, + void *void_arg), + void *void_arg) +{ +int found_hier=MAILBOX_NOSELECT; +int is_interesting; +int i,j,bad_pattern; +struct hierlist *hierarchies, *folders, *hp; +struct list_sharable_info shared_info; + +const char *obsolete; +int check_all_folders=0; +char hiersepbuf[8]; +int callback_rc=0; + + obsolete=getenv("IMAP_CHECK_ALL_FOLDERS"); + if (obsolete && atoi(obsolete)) + check_all_folders=1; + + obsolete=getenv("IMAP_OBSOLETE_CLIENT"); + + if (obsolete && atoi(obsolete) == 0) + obsolete=0; + + /* Allow up to ten wildcards */ + + for (i=j=0; pattern[i]; i++) + if (pattern[i] == '*' || pattern[i] == '%') ++j; + bad_pattern= j > 10; + + if (list_options & LIST_CHECK1FOLDER) + bad_pattern=0; + + if (bad_pattern) + { + errno=EINVAL; + return -1; + } + + hierarchies=0; + folders=0; + + match_mailbox_prep(pattern); + + shared_info.pattern=pattern; + shared_info.folders= &folders; + shared_info.hierarchies= &hierarchies; + shared_info.flags=list_options; + shared_info.callback_func=callback_func; + shared_info.cb_arg=void_arg; + + if (!(list_options & LIST_SUBSCRIBED)) + { + if (strncmp(pattern, NEWSHARED, + sizeof(NEWSHARED)-1) == 0) + { + list_newshared(pattern + + sizeof(NEWSHARED)-1, + &shared_info); + } + else + { + maildir_scan(".", INBOX, &shared_info); + + /* List sharable maildirs */ + + maildir_list_sharable( ".", &list_sharable, + &shared_info ); + } + } + else + { + list_subscribed(pattern, list_options, &folders, &hierarchies); + + /* List shared folders */ + + maildir_list_shared( ".", &list_sharable, + &shared_info ); + } + + while ((hp=folders) != 0) + { + struct hierlist *d; + int mb_flags; + + folders=hp->next; + + is_interesting= -1; + + if (strcmp(hp->hier, INBOX) == 0 || check_all_folders) + is_interesting=hasnewmsgs(hp->hier); + + strcat(strcat(strcpy(hiersepbuf, "\""), hierchs), "\""); + + mb_flags=0; + + if (is_interesting == 0) + { + mb_flags|=MAILBOX_UNMARKED; + } + if (is_interesting > 0) + { + mb_flags|=MAILBOX_MARKED; + } + + if ((d=search_hier(hierarchies, hp->hier)) == 0) + { + mb_flags |= + obsolete ? MAILBOX_NOINFERIORS:MAILBOX_NOCHILDREN; + } + else + { + d->flag=1; + if (!obsolete) + mb_flags |= MAILBOX_CHILDREN; + } + + if (isnullname) + found_hier=mb_flags; + else + if (callback_rc == 0) + callback_rc=(*callback_func) + (hiersepbuf, hp->hier, + mb_flags | list_options, void_arg); + free(hp); + } + + while ((hp=hierarchies) != 0) + { + hierarchies=hp->next; + + match_mailbox_prep(hp->hier); + + if (match_mailbox(hp->hier, pattern, list_options) == 0 + && hp->flag == 0) + { + int mb_flags=MAILBOX_NOSELECT; + + if (!obsolete) + mb_flags |= MAILBOX_CHILDREN; + + if (isnullname) + found_hier=mb_flags; + else + { + strcat(strcat(strcpy(hiersepbuf, "\""), + hierchs), "\""); + + if (callback_rc == 0) + callback_rc=(*callback_func) + (hiersepbuf, + hp->hier, + mb_flags | list_options, + void_arg); + } + } + free(hp); + } + + if (isnullname) + { + const char *namesp=""; + + if (strncmp(pattern, NEWSHARED, sizeof(NEWSHARED)-1) == 0) + namesp=NEWSHARED; + + strcat(strcat(strcpy(hiersepbuf, "\""), hierchs), "\""); + + if (callback_rc == 0) + callback_rc=(*callback_func) + (hiersepbuf, namesp, found_hier | list_options, + void_arg); + } + return callback_rc; +} + +static int match_recursive(char *, char *, int); + +static void match_mailbox_prep(char *name) +{ + size_t i; + + /* First component, INBOX, is case insensitive */ + + if ( +#if HAVE_STRNCASECMP + strncasecmp(name, INBOX, sizeof(INBOX)-1) == 0 +#else + strnicmp(name, INBOX, sizeof(INBOX)-1) == 0 +#endif + ) + for (i=0; name[i] && name[i] != HIERCH; i++) + name[i]=toupper( (int)(unsigned char)name[i] ); + + /* ... except that "shared" should be lowercase ... */ + + if (memcmp(name, "SHARED", 6) == 0) + memcpy(name, "shared", 6); +} + +static int match_mailbox(char *name, char *pattern, int list_options) +{ + if (list_options & LIST_CHECK1FOLDER) + return strcmp(name, pattern); + + return (match_recursive(name, pattern, HIERCH)); +} + +static int match_recursive(char *name, char *pattern, int hierch) +{ + for (;;) + { + if (*pattern == '*') + { + do + { + if (match_recursive(name, pattern+1, + hierch) == 0) + return (0); + } while (*name++); + return (-1); + } + if (*pattern == '%') + { + do + { + if (match_recursive(name, pattern+1, hierch) + == 0) return (0); + if (*name == hierch) break; + } while (*name++); + return (-1); + } + if (*name == 0 && *pattern == 0) break; + if (*name == 0 || *pattern == 0) return (-1); + if (*name != *pattern) return (-1); + ++name; + ++pattern; + } + return (0); +} |
