Annotation of ircnowd/src/ngircd/match.c, Revision 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