Hello All!
I changed the Matche() function in match.c to work with REGCOMP(3) (regular expressions). This adds several possibilities in the conf file. Now you can write something like:
[Operator] Mask = d-?ra[0-9x]?!~?d-?ra@.*.d-ra.net
The default Mask had to be changed slightly:
Mask = .*!ident@somewhere.example.com
Another advantage: The source code is much more shorter! Keep it as simple as possible - but not simpler!
The patch:
Index: ngircd/doc/sample-ngircd.conf =================================================================== RCS file: /srv/cvs/ngircd/ngircd/doc/sample-ngircd.conf,v retrieving revision 1.37 diff -u -p -r1.37 sample-ngircd.conf --- ngircd/doc/sample-ngircd.conf 9 Apr 2006 12:27:23 -0000 1.37 +++ ngircd/doc/sample-ngircd.conf 5 Oct 2006 16:14:45 -0000 @@ -115,7 +115,7 @@ ;Password = ThePwd
# Optional Mask from which /OPER will be accepted - ;Mask = *!ident@somewhere.example.com + ;Mask = .*!ident@somewhere.example.com
[Operator] # More [Operator] sections, if you like ... Index: ngircd/src/ngircd/match.c =================================================================== RCS file: /srv/cvs/ngircd/ngircd/src/ngircd/match.c,v retrieving revision 1.4 diff -u -p -r1.4 match.c --- ngircd/src/ngircd/match.c 31 Jul 2005 20:13:08 -0000 1.4 +++ ngircd/src/ngircd/match.c 5 Oct 2006 16:14:46 -0000 @@ -19,6 +19,8 @@ static char UNUSED id[] = "$Id: match.c, #include "imp.h" #include <assert.h> #include <string.h> +#include <sys/types.h> +#include <regex.h>
#include "exp.h" #include "match.h" @@ -33,9 +35,9 @@ static char UNUSED id[] = "$Id: match.c,
static int Matche PARAMS(( char *p, char *t )); -static int Matche_After_Star PARAMS(( char *p, char *t ));
+#define MATCH_NONE 7 /* no match in regexec */ #define MATCH_PATTERN 6 /* bad pattern */ #define MATCH_LITERAL 5 /* match failure on literal match */ #define MATCH_RANGE 4 /* match failure on [..] construct */ @@ -52,202 +54,27 @@ Match( char *Pattern, char *String ) else return false; } /* Match */
- +/* + * p = pattern + * t = input text + * + * */ static int Matche( char *p, char *t ) { - register char range_start, range_end; - bool invert; - bool member_match; - bool loop; + int erg, status; + regex_t preg;
- for( ; *p; p++, t++ ) + status = regcomp(&preg, p, REG_EXTENDED|REG_NOSUB); + if ( status != 0 ) + erg = MATCH_PATTERN; + else { - /* if this is the end of the text then this is the end of the match */ - if( ! *t ) - { - return ( *p == '*' && *++p == '\0' ) ? MATCH_VALID : MATCH_ABORT; - } - - /* determine and react to pattern type */ - switch( *p ) - { - case '?': /* single any character match */ - break; - - 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: - if( *p != *t ) return MATCH_LITERAL; - } + status = regexec(&preg, t, (size_t)0, NULL, 0); + erg = status ? MATCH_NONE : MATCH_VALID; } - /* if end of text not reached then the pattern fails */ - - if( *t ) return MATCH_END; - else return MATCH_VALID; + regfree(&preg); + return erg; } /* Matche */
- -static int -Matche_After_Star( char *p, char *t ) -{ - register int nextp, match = 0; - - /* pass over existing ? and * in pattern */ - while( *p == '?' || *p == '*' ) - { - /* take one char for each ? and + */ - if (*p == '?') - { - /* if end of text then no match */ - if( ! *t++ ) return MATCH_ABORT; - } - - /* move to next char in pattern */ - p++; - } - - /* if end of pattern we have matched regardless of text left */ - if( ! *p ) return MATCH_VALID; - - /* get the next character to match which must be a literal or '[' */ - nextp = *p; - if( nextp == '\' ) - { - nextp = p[1]; - - /* if end of text then we have a bad pattern */ - if( ! nextp ) return MATCH_PATTERN; - } - - /* Continue until we run out of text or definite result seen */ - do - { - /* a precondition for matching is that the next character - * in the pattern match the next character in the text or that - * the next pattern char is the beginning of a range. Increment - * text pointer as we go here */ - if( nextp == *t || nextp == '[' ) match = Matche( p, t ); - - /* if the end of text is reached then no match */ - if( ! *t++ ) match = MATCH_ABORT; - } while( match != MATCH_VALID && match != MATCH_ABORT && match != MATCH_PATTERN ); - - /* return result */ - return match; -} /* Matche_After_Star */ - - /* -eof- */
Regards Dieter
Dieter Rauschenberger dr@d-ra.de wrote:
I changed the Matche() function in match.c to work with REGCOMP(3) (regular expressions). This adds several possibilities in the conf file. Now you can write something like:
[Operator] Mask = d-?ra[0-9x]?!~?d-?ra@.*.d-ra.net
The default Mask had to be changed slightly:
Mask = .*!ident@somewhere\.example\.com
Another advantage: The source code is much more shorter! Keep it as simple as possible - but not simpler!
I Agree, but recomp treats several special characters differently. Matche() is also used for ban and invite lists -- your patch breaks this:
20:00 -!- mode/#bla [+b *!*@localhost] by test 20:00 -!- fw [~me@localhost] has joined #bla
Florian
On Thu, Oct 05, 2006 at 07:52:51PM +0200, Florian Westphal wrote:
... Matche() is also used for ban and invite lists -- your patch breaks this:
20:00 -!- mode/#bla [+b *!*@localhost] by test 20:00 -!- fw [~me@localhost] has joined #bla
ARGH ! I have not checked this. Thanks for information!
Regards Dieter