mirror of
				https://github.com/Icinga/icinga2.git
				synced 2025-11-04 05:34:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			310 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			310 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * IRC - Internet Relay Chat, common/match.c
 | 
						|
 * Copyright (C) 1990 Jarkko Oikarinen
 | 
						|
 *
 | 
						|
 * 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
 | 
						|
 * the Free Software Foundation; either version 1, or (at your option)
 | 
						|
 * any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 *
 | 
						|
 * $Id: Match.cpp,v 1.2 2005/08/15 10:08:50 shroud23 Exp $
 | 
						|
 */
 | 
						|
 | 
						|
#include <ctype.h>
 | 
						|
#include "mmatch.h"
 | 
						|
 | 
						|
#define ToLower tolower
 | 
						|
 | 
						|
/*
 | 
						|
 * mmatch()
 | 
						|
 *
 | 
						|
 * Written by Run (carlo@runaway.xs4all.nl), 25-10-96
 | 
						|
 *
 | 
						|
 *
 | 
						|
 * From: Carlo Wood <carlo@runaway.xs4all.nl>
 | 
						|
 * Message-Id: <199609021026.MAA02393@runaway.xs4all.nl>
 | 
						|
 * Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem)
 | 
						|
 * To: coder-com@mail.undernet.org (coder committee)
 | 
						|
 * Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST)
 | 
						|
 *
 | 
						|
 * We need a new function `mmatch(const char *old_mask, const char *new_mask)'
 | 
						|
 * which returns `true' likewise the current `match' (start with copying it),
 | 
						|
 * but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !)
 | 
						|
 * as follows:  a '*' in `new_mask' does not match a '?' in `old_mask' and
 | 
						|
 * a '?' in `new_mask' does not match a '\?' in `old_mask'.
 | 
						|
 * And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'...
 | 
						|
 * And last but not least, '\?' and '\*' in `new_mask' now become one character.
 | 
						|
 */
 | 
						|
 | 
						|
#if 0
 | 
						|
int mmatch(const char *old_mask, const char *new_mask)
 | 
						|
{
 | 
						|
  const char *m = old_mask;
 | 
						|
  const char *n = new_mask;
 | 
						|
  const char *ma = m;
 | 
						|
  const char *na = n;
 | 
						|
  int wild = 0;
 | 
						|
  int mq = 0, nq = 0;
 | 
						|
 | 
						|
  while (1)
 | 
						|
  {
 | 
						|
    if (*m == '*')
 | 
						|
    {
 | 
						|
      while (*m == '*')
 | 
						|
        m++;
 | 
						|
      wild = 1;
 | 
						|
      ma = m;
 | 
						|
      na = n;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!*m)
 | 
						|
    {
 | 
						|
      if (!*n)
 | 
						|
        return 0;
 | 
						|
      for (m--; (m > old_mask) && (*m == '?'); m--)
 | 
						|
        ;
 | 
						|
      if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
 | 
						|
        return 0;
 | 
						|
      if (!wild)
 | 
						|
        return 1;
 | 
						|
      m = ma;
 | 
						|
 | 
						|
      /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
 | 
						|
      if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
 | 
						|
        ++na;
 | 
						|
 | 
						|
      n = ++na;
 | 
						|
    }
 | 
						|
    else if (!*n)
 | 
						|
    {
 | 
						|
      while (*m == '*')
 | 
						|
        m++;
 | 
						|
      return (*m != 0);
 | 
						|
    }
 | 
						|
    if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
 | 
						|
    {
 | 
						|
      m++;
 | 
						|
      mq = 1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      mq = 0;
 | 
						|
 | 
						|
    /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
 | 
						|
    if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?')))
 | 
						|
    {
 | 
						|
      n++;
 | 
						|
      nq = 1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      nq = 0;
 | 
						|
 | 
						|
/*
 | 
						|
 * This `if' has been changed compared to match() to do the following:
 | 
						|
 * Match when:
 | 
						|
 *   old (m)         new (n)         boolean expression
 | 
						|
 *    *               any             (*m == '*' && !mq) ||
 | 
						|
 *    ?               any except '*'  (*m == '?' && !mq && (*n != '*' || nq)) ||
 | 
						|
 * any except * or ?  same as m       (!((*m == '*' || *m == '?') && !mq) &&
 | 
						|
 *                                      ToLower(*m) == ToLower(*n) &&
 | 
						|
 *                                        !((mq && !nq) || (!mq && nq)))
 | 
						|
 *
 | 
						|
 * Here `any' also includes \* and \? !
 | 
						|
 *
 | 
						|
 * After reworking the boolean expressions, we get:
 | 
						|
 * (Optimized to use boolean shortcircuits, with most frequently occuring
 | 
						|
 *  cases upfront (which took 2 hours!)).
 | 
						|
 */
 | 
						|
    if ((*m == '*' && !mq) ||
 | 
						|
        ((!mq || nq) && ToLower(*m) == ToLower(*n)) ||
 | 
						|
        (*m == '?' && !mq && (*n != '*' || nq)))
 | 
						|
    {
 | 
						|
      if (*m)
 | 
						|
        m++;
 | 
						|
      if (*n)
 | 
						|
        n++;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (!wild)
 | 
						|
        return 1;
 | 
						|
      m = ma;
 | 
						|
 | 
						|
      /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
 | 
						|
      if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
 | 
						|
        ++na;
 | 
						|
 | 
						|
      n = ++na;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * Compare if a given string (name) matches the given
 | 
						|
 * mask (which can contain wild cards: '*' - match any
 | 
						|
 * number of chars, '?' - match any single character.
 | 
						|
 *
 | 
						|
 * return  0, if match
 | 
						|
 *         1, if no match
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * match
 | 
						|
 *
 | 
						|
 * Rewritten by Andrea Cocito (Nemesi), November 1998.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/****************** Nemesi's match() ***************/
 | 
						|
 | 
						|
int match(const char *mask, const char *str)
 | 
						|
{
 | 
						|
  const char *m = mask, *s = str;
 | 
						|
  char ch;
 | 
						|
  const char *bm, *bs;          /* Will be reg anyway on a decent CPU/compiler */
 | 
						|
 | 
						|
  /* Process the "head" of the mask, if any */
 | 
						|
  while ((ch = *m++) && (ch != '*'))
 | 
						|
    switch (ch)
 | 
						|
    {
 | 
						|
      case '\\':
 | 
						|
        if (*m == '?' || *m == '*')
 | 
						|
          ch = *m++;
 | 
						|
      default:
 | 
						|
        if (ToLower(*s) != ToLower(ch))
 | 
						|
          return 1;
 | 
						|
      case '?':
 | 
						|
        if (!*s++)
 | 
						|
          return 1;
 | 
						|
    };
 | 
						|
  if (!ch)
 | 
						|
    return *s;
 | 
						|
 | 
						|
  /* We got a star: quickly find if/where we match the next char */
 | 
						|
got_star:
 | 
						|
  bm = m;                       /* Next try rollback here */
 | 
						|
  while ((ch = *m++))
 | 
						|
    switch (ch)
 | 
						|
    {
 | 
						|
      case '?':
 | 
						|
        if (!*s++)
 | 
						|
          return 1;
 | 
						|
      case '*':
 | 
						|
        bm = m;
 | 
						|
        continue;               /* while */
 | 
						|
      case '\\':
 | 
						|
        if (*m == '?' || *m == '*')
 | 
						|
          ch = *m++;
 | 
						|
      default:
 | 
						|
        goto break_while;       /* C is structured ? */
 | 
						|
    };
 | 
						|
break_while:
 | 
						|
  if (!ch)
 | 
						|
    return 0;                   /* mask ends with '*', we got it */
 | 
						|
  ch = ToLower(ch);
 | 
						|
  if (!*s)			/* String is already empty, don't continue */
 | 
						|
    return 1;			/* This fixes the #quakenet access denied bug */
 | 
						|
  while (ToLower(*s++) != ch)
 | 
						|
    if (!*s)
 | 
						|
      return 1;
 | 
						|
  bs = s;                       /* Next try start from here */
 | 
						|
 | 
						|
  /* Check the rest of the "chunk" */
 | 
						|
  while ((ch = *m++))
 | 
						|
  {
 | 
						|
    switch (ch)
 | 
						|
    {
 | 
						|
      case '*':
 | 
						|
        goto got_star;
 | 
						|
      case '\\':
 | 
						|
        if (*m == '?' || *m == '*')
 | 
						|
          ch = *m++;
 | 
						|
      default:
 | 
						|
        if (ToLower(*s) != ToLower(ch))
 | 
						|
        {
 | 
						|
          /* If we've run out of string, give up */
 | 
						|
          if (!*bs)
 | 
						|
            return 1;
 | 
						|
          m = bm;
 | 
						|
          s = bs;
 | 
						|
          goto got_star;
 | 
						|
        };
 | 
						|
      case '?':
 | 
						|
        if (!*s++)
 | 
						|
          return 1;
 | 
						|
    };
 | 
						|
  };
 | 
						|
  if (*s)
 | 
						|
  {
 | 
						|
    m = bm;
 | 
						|
    s = bs;
 | 
						|
    goto got_star;
 | 
						|
  };
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * collapse()
 | 
						|
 * Collapse a pattern string into minimal components.
 | 
						|
 * This particular version is "in place", so that it changes the pattern
 | 
						|
 * which is to be reduced to a "minimal" size.
 | 
						|
 *
 | 
						|
 * (C) Carlo Wood - 6 Oct 1998
 | 
						|
 * Speedup rewrite by Andrea Cocito, December 1998.
 | 
						|
 * Note that this new optimized alghoritm can *only* work in place.
 | 
						|
 */
 | 
						|
 | 
						|
#if 0
 | 
						|
char *collapse(char *pattern)
 | 
						|
{
 | 
						|
  int star = 0;
 | 
						|
  char *m = pattern;
 | 
						|
  char *b;
 | 
						|
 | 
						|
  if (m)
 | 
						|
  {
 | 
						|
    do
 | 
						|
    {
 | 
						|
      if ((*m == '*') && ((m[1] == '*') || (m[1] == '?')))
 | 
						|
      {
 | 
						|
        b = m;
 | 
						|
        do
 | 
						|
        {
 | 
						|
          if (*m == '*')
 | 
						|
            star = 1;
 | 
						|
          else
 | 
						|
          {
 | 
						|
            if (star && (*m != '?'))
 | 
						|
            {
 | 
						|
              *b++ = '*';
 | 
						|
              star = 0;
 | 
						|
            };
 | 
						|
            *b++ = *m;
 | 
						|
            if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
 | 
						|
              *b++ = *++m;
 | 
						|
          };
 | 
						|
        }
 | 
						|
        while (*m++);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
 | 
						|
          m++;
 | 
						|
      };
 | 
						|
    }
 | 
						|
    while (*m++);
 | 
						|
  };
 | 
						|
  return pattern;
 | 
						|
}
 | 
						|
#endif
 |