/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2018 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Wildcard pattern matching
*/
-#include "imp.h"
#include <assert.h>
#include <string.h>
-#include "exp.h"
-#include "match.h"
#include "defines.h"
#include "tool.h"
+#include "match.h"
/*
* The pattern matching functions [Matche(), Matche_After_Star()] are based
* "public domain": <http://c.snippets.org/snip_lister.php?fname=match.c>
*/
-
static int Matche PARAMS(( const char *p, const char *t ));
static int Matche_After_Star PARAMS(( const char *p, const char *t ));
-
#define MATCH_PATTERN 6 /**< bad pattern */
#define MATCH_LITERAL 5 /**< match failure on literal match */
#define MATCH_RANGE 4 /**< match failure on [..] construct */
#define MATCH_END 2 /**< premature end of pattern string */
#define MATCH_VALID 1 /**< valid match */
-
/**
* Match string with pattern.
*
- * @param Pattern Pattern to match with
- * @param String Input string
- * @return true if pattern matches
+ * @param Pattern Pattern to match with
+ * @param String Input string
+ * @return true if pattern matches
*/
GLOBAL bool
Match( const char *Pattern, const char *String )
{
- /* Pattern mit String vergleichen */
- if( Matche( Pattern, String ) == MATCH_VALID ) return true;
- else return false;
+ if (Matche(Pattern, String) == MATCH_VALID)
+ return true;
+ else
+ return false;
} /* Match */
-
/**
* Match string with pattern case-insensitive.
*
- * @param pattern Pattern to match with
- * @param searchme Input string, at most COMMAND_LEN-1 characters long
- * @return true if pattern matches
+ * @param Pattern Pattern to match with
+ * @param String Input string, at most COMMAND_LEN-1 characters long
+ * @return true if pattern matches
*/
GLOBAL bool
-MatchCaseInsensitive(const char *pattern, const char *searchme)
+MatchCaseInsensitive(const char *Pattern, const char *String)
{
- char haystack[COMMAND_LEN];
+ char needle[COMMAND_LEN], haystack[COMMAND_LEN];
+
+ strlcpy(needle, Pattern, sizeof(needle));
+ strlcpy(haystack, String, sizeof(haystack));
- strlcpy(haystack, searchme, sizeof(haystack));
- return Match(pattern, ngt_LowerStr(haystack));
+ return Match(ngt_LowerStr(needle), ngt_LowerStr(haystack));
} /* MatchCaseInsensitive */
+/**
+ * Match string with pattern case-insensitive.
+ *
+ * @param Pattern Pattern to match with
+ * @param String Input string, at most COMMAND_LEN-1 characters long
+ * @param Separator Character separating the individual patterns in the list
+ * @return true if pattern matches
+ */
+GLOBAL bool
+MatchCaseInsensitiveList(const char *Pattern, const char *String,
+ const char *Separator)
+{
+ char tmp_pattern[COMMAND_LEN], *ptr;
+
+ strlcpy(tmp_pattern, Pattern, sizeof(tmp_pattern));
+
+ ptr = strtok(tmp_pattern, Separator);
+ while (ptr) {
+ ngt_TrimStr(ptr);
+ if (MatchCaseInsensitive(ptr, String))
+ return true;
+ ptr = strtok(NULL, Separator);
+ }
+ return false;
+} /* MatchCaseInsensitive */
static int
Matche( const char *p, const char *t )
{
- register char range_start, range_end;
- bool invert;
- bool member_match;
- bool loop;
-
for( ; *p; p++, t++ )
{
/* if this is the end of the text then this is the end of the match */
case '*': /* multiple any character match */
return Matche_After_Star( p, t );
- case '[': /* [..] construct, single member/exclusion character match */
- /* move to beginning of range */
- p++;
-
- /* check if this is a member match or exclusion match */
- invert = false;
- if( *p == '!' || *p == '^' )
- {
- invert = true;
- p++;
- }
-
- /* if closing bracket here or at range start then we have a malformed pattern */
- if ( *p == ']' ) return MATCH_PATTERN;
-
- member_match = false;
- loop = true;
-
- while( loop )
- {
- /* if end of construct then loop is done */
- if( *p == ']' )
- {
- loop = false;
- continue;
- }
-
- /* matching a '!', '^', '-', '\' or a ']' */
- if( *p == '\\' ) range_start = range_end = *++p;
- else range_start = range_end = *p;
-
- /* if end of pattern then bad pattern (Missing ']') */
- if( ! *p ) return MATCH_PATTERN;
-
- /* check for range bar */
- if( *++p == '-' )
- {
- /* get the range end */
- range_end = *++p;
-
- /* if end of pattern or construct then bad pattern */
- if( range_end == '\0' || range_end == ']' ) return MATCH_PATTERN;
-
- /* special character range end */
- if( range_end == '\\' )
- {
- range_end = *++p;
-
- /* if end of text then we have a bad pattern */
- if ( ! range_end ) return MATCH_PATTERN;
- }
-
- /* move just beyond this range */
- p++;
- }
-
- /* if the text character is in range then match found. make sure the range
- * letters have the proper relationship to one another before comparison */
- if( range_start < range_end )
- {
- if( *t >= range_start && *t <= range_end )
- {
- member_match = true;
- loop = false;
- }
- }
- else
- {
- if( *t >= range_end && *t <= range_start )
- {
- member_match = true;
- loop = false;
- }
- }
- }
-
- /* if there was a match in an exclusion set then no match */
- /* if there was no match in a member set then no match */
- if(( invert && member_match ) || ! ( invert || member_match )) return MATCH_RANGE;
-
- /* if this is not an exclusion then skip the rest of the [...]
- * construct that already matched. */
- if( member_match )
- {
- while( *p != ']' )
- {
- /* bad pattern (Missing ']') */
- if( ! *p ) return MATCH_PATTERN;
-
- /* skip exact match */
- if( *p == '\\' )
- {
- p++;
-
- /* if end of text then we have a bad pattern */
- if( ! *p ) return MATCH_PATTERN;
- }
-
- /* move to next pattern char */
- p++;
- }
- }
- break;
- case '\\': /* next character is quoted and must match exactly */
- /* move pattern pointer to quoted char and fall through */
- p++;
-
- /* if end of text then we have a bad pattern */
- if( ! *p ) return MATCH_PATTERN;
-
- /* must match this character exactly */
- default:
+ default: /* must match this character exactly */
if( *p != *t ) return MATCH_LITERAL;
}
}
else return MATCH_VALID;
} /* Matche */
-
static int
Matche_After_Star( const char *p, const char *t )
{
return match;
} /* Matche_After_Star */
-
/* -eof- */