Annotation of ircnowd/src/ngircd/match.c, Revision 1.1.1.1
1.1 tomglok 1: /*
2: * ngIRCd -- The Next Generation IRC Daemon
3: * Copyright (c)2001-2018 Alexander Barton (alex@barton.de) and Contributors.
4: *
5: * This program is free software; you can redistribute it and/or modify
6: * it under the terms of the GNU General Public License as published by
7: * the Free Software Foundation; either version 2 of the License, or
8: * (at your option) any later version.
9: * Please read the file COPYING, README and AUTHORS for more information.
10: */
11:
12: #include "portab.h"
13:
14: /**
15: * @file
16: * Wildcard pattern matching
17: */
18:
19: #include <assert.h>
20: #include <string.h>
21:
22: #include "defines.h"
23: #include "tool.h"
24:
25: #include "match.h"
26:
27: /*
28: * The pattern matching functions [Matche(), Matche_After_Star()] are based
29: * on code of J. Kercheval. Version 1.1 has been released on 1991-03-12 as
30: * "public domain": <http://c.snippets.org/snip_lister.php?fname=match.c>
31: */
32:
33: static int Matche PARAMS(( const char *p, const char *t ));
34: static int Matche_After_Star PARAMS(( const char *p, const char *t ));
35:
36: #define MATCH_PATTERN 6 /**< bad pattern */
37: #define MATCH_LITERAL 5 /**< match failure on literal match */
38: #define MATCH_RANGE 4 /**< match failure on [..] construct */
39: #define MATCH_ABORT 3 /**< premature end of text string */
40: #define MATCH_END 2 /**< premature end of pattern string */
41: #define MATCH_VALID 1 /**< valid match */
42:
43: /**
44: * Match string with pattern.
45: *
46: * @param Pattern Pattern to match with
47: * @param String Input string
48: * @return true if pattern matches
49: */
50: GLOBAL bool
51: Match( const char *Pattern, const char *String )
52: {
53: if (Matche(Pattern, String) == MATCH_VALID)
54: return true;
55: else
56: return false;
57: } /* Match */
58:
59: /**
60: * Match string with pattern case-insensitive.
61: *
62: * @param Pattern Pattern to match with
63: * @param String Input string, at most COMMAND_LEN-1 characters long
64: * @return true if pattern matches
65: */
66: GLOBAL bool
67: MatchCaseInsensitive(const char *Pattern, const char *String)
68: {
69: char needle[COMMAND_LEN], haystack[COMMAND_LEN];
70:
71: strlcpy(needle, Pattern, sizeof(needle));
72: strlcpy(haystack, String, sizeof(haystack));
73:
74: return Match(ngt_LowerStr(needle), ngt_LowerStr(haystack));
75: } /* MatchCaseInsensitive */
76:
77: /**
78: * Match string with pattern case-insensitive.
79: *
80: * @param Pattern Pattern to match with
81: * @param String Input string, at most COMMAND_LEN-1 characters long
82: * @param Separator Character separating the individual patterns in the list
83: * @return true if pattern matches
84: */
85: GLOBAL bool
86: MatchCaseInsensitiveList(const char *Pattern, const char *String,
87: const char *Separator)
88: {
89: char tmp_pattern[COMMAND_LEN], *ptr;
90:
91: strlcpy(tmp_pattern, Pattern, sizeof(tmp_pattern));
92:
93: ptr = strtok(tmp_pattern, Separator);
94: while (ptr) {
95: ngt_TrimStr(ptr);
96: if (MatchCaseInsensitive(ptr, String))
97: return true;
98: ptr = strtok(NULL, Separator);
99: }
100: return false;
101: } /* MatchCaseInsensitive */
102:
103: static int
104: Matche( const char *p, const char *t )
105: {
106: for( ; *p; p++, t++ )
107: {
108: /* if this is the end of the text then this is the end of the match */
109: if( ! *t )
110: {
111: return ( *p == '*' && *++p == '\0' ) ? MATCH_VALID : MATCH_ABORT;
112: }
113:
114: /* determine and react to pattern type */
115: switch( *p )
116: {
117: case '?': /* single any character match */
118: break;
119:
120: case '*': /* multiple any character match */
121: return Matche_After_Star( p, t );
122:
123: default: /* must match this character exactly */
124: if( *p != *t ) return MATCH_LITERAL;
125: }
126: }
127: /* if end of text not reached then the pattern fails */
128:
129: if( *t ) return MATCH_END;
130: else return MATCH_VALID;
131: } /* Matche */
132:
133: static int
134: Matche_After_Star( const char *p, const char *t )
135: {
136: register int nextp, match = 0;
137:
138: /* pass over existing ? and * in pattern */
139: while( *p == '?' || *p == '*' )
140: {
141: /* take one char for each ? and + */
142: if (*p == '?')
143: {
144: /* if end of text then no match */
145: if( ! *t++ ) return MATCH_ABORT;
146: }
147:
148: /* move to next char in pattern */
149: p++;
150: }
151:
152: /* if end of pattern we have matched regardless of text left */
153: if( ! *p ) return MATCH_VALID;
154:
155: /* get the next character to match which must be a literal or '[' */
156: nextp = *p;
157: if( nextp == '\\' )
158: {
159: nextp = p[1];
160:
161: /* if end of text then we have a bad pattern */
162: if( ! nextp ) return MATCH_PATTERN;
163: }
164:
165: /* Continue until we run out of text or definite result seen */
166: do
167: {
168: /* a precondition for matching is that the next character
169: * in the pattern match the next character in the text or that
170: * the next pattern char is the beginning of a range. Increment
171: * text pointer as we go here */
172: if( nextp == *t || nextp == '[' ) match = Matche( p, t );
173:
174: /* if the end of text is reached then no match */
175: if( ! *t++ ) match = MATCH_ABORT;
176: } while( match != MATCH_VALID && match != MATCH_ABORT && match != MATCH_PATTERN );
177:
178: /* return result */
179: return match;
180: } /* Matche_After_Star */
181:
182: /* -eof- */
CVSweb