1 /* ========================================================================
2  * Copyright 1988-2006 University of Washington
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *
11  * ========================================================================
12  */
13 
14 /*
15  * Program:	IMAP Wildcard Matching Routines (case-independent)
16  *
17  * Author:	Mark Crispin
18  *		Networks and Distributed Computing
19  *		Computing & Communications
20  *		University of Washington
21  *		Administration Building, AG-44
22  *		Seattle, WA  98195
23  *		Internet: MRC@CAC.Washington.EDU
24  *
25  * Date:	15 June 2000
26  * Last Edited:	30 August 2006
27  */
28 
29 /* Wildcard pattern match
30  * Accepts: base string
31  *	    pattern string
32  *	    delimiter character
33  * Returns: T if pattern matches base, else NIL
34  */
35 
pmatch_full(unsigned char * s,unsigned char * pat,unsigned char delim)36 long pmatch_full (unsigned char *s,unsigned char *pat,unsigned char delim)
37 {
38   switch (*pat) {
39   case '%':			/* non-recursive */
40 				/* % at end, OK if no inferiors */
41     if (!pat[1]) return (delim && strchr (s,delim)) ? NIL : T;
42                                 /* scan remainder of string until delimiter */
43     do if (pmatch_full (s,pat+1,delim)) return T;
44     while ((*s != delim) && *s++);
45     break;
46   case '*':			/* match 0 or more characters */
47     if (!pat[1]) return T;	/* * at end, unconditional match */
48 				/* scan remainder of string */
49     do if (pmatch_full (s,pat+1,delim)) return T;
50     while (*s++);
51     break;
52   case '\0':			/* end of pattern */
53     return *s ? NIL : T;	/* success if also end of base */
54   default:			/* match this character */
55     return compare_uchar (*pat,*s) ? NIL : pmatch_full (s+1,pat+1,delim);
56   }
57   return NIL;
58 }
59 
60 /* Directory pattern match
61  * Accepts: base string
62  *	    pattern string
63  *	    delimiter character
64  * Returns: T if base is a matching directory of pattern, else NIL
65  */
66 
dmatch(unsigned char * s,unsigned char * pat,unsigned char delim)67 long dmatch (unsigned char *s,unsigned char *pat,unsigned char delim)
68 {
69   switch (*pat) {
70   case '%':			/* non-recursive */
71     if (!*s) return T;		/* end of base means have a subset match */
72     if (!*++pat) return NIL;	/* % at end, no inferiors permitted */
73 				/* scan remainder of string until delimiter */
74     do if (dmatch (s,pat,delim)) return T;
75     while ((*s != delim) && *s++);
76     if (*s && !s[1]) return T;	/* ends with delimiter, must be subset */
77     return dmatch (s,pat,delim);/* do new scan */
78   case '*':			/* match 0 or more characters */
79     return T;			/* unconditional match */
80   case '\0':			/* end of pattern */
81     break;
82   default:			/* match this character */
83     if (*s) return compare_uchar (*pat,*s) ? NIL : dmatch (s+1,pat+1,delim);
84 				/* end of base, return if at delimiter */
85     else if (*pat == delim) return T;
86     break;
87   }
88   return NIL;
89 }
90