ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/match.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/match.c (file contents):
Revision 1652 by michael, Tue Nov 13 20:28:53 2012 UTC vs.
Revision 1653 by michael, Wed Nov 14 11:50:55 2012 UTC

# Line 25 | Line 25
25   #include "client.h"
26   #include "ircd.h"
27  
28 /* Fix "statement not reached" warnings on Sun WorkShop C */
29 #ifdef __SUNPRO_C
30 #   pragma error_messages(off, E_STATEMENT_NOT_REACHED)
31 #endif
32
33 /* match()
34 *
35 *  Compare if a given string (name) matches the given
36 *  mask (which can contain wild cards: '*' - match any
37 *  number of chars, '?' - match any single character.
38 *
39 *      return  1, if match
40 *              0, if no match
41 *
42 *  Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
43 */
44 int
45 match(const char *mask, const char *name)
46 {
47  const unsigned char *m = (const unsigned char *)mask;
48  const unsigned char *n = (const unsigned char *)name;
49  const unsigned char *ma = NULL;
50  const unsigned char *na = (const unsigned char *)name;
51
52  assert(mask != NULL);
53  assert(name != NULL);
54
55  while (1)
56  {
57    if (*m == '*')
58    {
59      while (*m == '*')
60        m++;
61      ma = m;
62      na = n;
63    }
64
65    if (!*m)
66    {
67      if (!*n)
68        return 0;
69      if (!ma)
70        return 1;
71      for (m--; (m > (const unsigned char *)mask) && (*m == '?'); m--)
72        ;
73      if (*m == '*')
74        return 0;
75      m = ma;
76      n = ++na;
77    }
78    else if (!*n)
79    {
80      while (*m == '*')
81        m++;
82      return *m != '\0';
83    }
84
85    if (ToLower(*m) != ToLower(*n) && *m != '?' && (*m != '#' || !IsDigit(*n)))
86    {
87      if (!ma)
88        return 1;
89      m = ma;
90      n = ++na;
91    }
92    else
93      m++, n++;
94  }
95
96  return 1;
97 }
28  
29 < /* match_esc()
30 < *
31 < * The match() function with support for escaping characters such
32 < * as '*' and '?'
29 > /*! \brief Check a string against a mask.
30 > * This test checks using traditional IRC wildcards only: '*' means
31 > * match zero or more characters of any type; '?' means match exactly
32 > * one character of any type.  A backslash escapes the next character
33 > * so that a wildcard may be matched exactly.
34 > * param mask Wildcard-containing mask.
35 > * param name String to check against \a mask.
36 > * return Zero if \a mask matches \a name, non-zero if no match.
37   */
38   int
39 < match_esc(const char *mask, const char *name)
39 > match(const char *mask, const char *name)
40   {
41 <  const unsigned char *m = (const unsigned char *)mask;
42 <  const unsigned char *n = (const unsigned char *)name;
43 <  const unsigned char *ma = NULL;
110 <  const unsigned char *na = (const unsigned char *)name;
111 <
112 <  assert(mask != NULL);
113 <  assert(name != NULL);
41 >  const char *m = mask, *n = name;
42 >  const char *m_tmp = mask, *n_tmp = name;
43 >  int star = 0;
44  
45    while (1)
46    {
47 <    if (*m == '*')
47 >    switch (*m)
48      {
49 <      while (*m == '*')
49 >      case '\0':
50 >        if (!*n)
51 >          return 0;
52 >  backtrack:
53 >        if (m_tmp == mask)
54 >          return 1;
55 >        m = m_tmp;
56 >        n = ++n_tmp;
57 >        if (*n == '\0')
58 >          return 1;
59 >        break;
60 >      case '\\':
61          m++;
62 <      ma = m;
63 <      na = n;
64 <    }
62 >        /* allow escaping to force capitalization */
63 >        if (*m++ != *n++)
64 >          goto backtrack;
65 >        break;
66 >      case '*':
67 >      case '?':
68 >        for (star = 0; ; m++)
69 >        {
70 >          if (*m == '*')
71 >            star = 1;
72 >          else if (*m == '?')
73 >          {
74 >            if (!*n++)
75 >              goto backtrack;
76 >          }
77 >          else
78 >            break;
79 >        }
80  
81 <    if (!*m)
82 <    {
83 <      if (!*n)
84 <        return 0;
85 <      if (!ma)
86 <        return 1;
87 <      for (m--; (m > (const unsigned char *)mask) && (*m == '?'); m--)
88 <        ;
89 <      if (*m == '*')
90 <        return 0;
91 <      m = ma;
92 <      n = ++na;
93 <    }
94 <    else if (!*n)
95 <    {
96 <      while (*m == '*')
81 >        if (star)
82 >        {
83 >          if (!*m)
84 >            return 0;
85 >          else if (*m == '\\')
86 >          {
87 >            m_tmp = ++m;
88 >            if (!*m)
89 >              return 1;
90 >            for (n_tmp = n; *n && *n != *m; n++)
91 >              ;
92 >          }
93 >          else
94 >          {
95 >            m_tmp = m;
96 >            for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++)
97 >              ;
98 >          }
99 >        }
100 >        /* and fall through */
101 >      default:
102 >        if (!*n)
103 >          return *m != '\0';
104 >        if (ToLower(*m) != ToLower(*n))
105 >          goto backtrack;
106          m++;
107 <      return *m != '\0';
108 <    }
144 <
145 <    if (*m != '?' && (*m != '#' || IsDigit(*n)))
146 <    {
147 <      if (*m == '\\')
148 <        if (!*++m)
149 <          return 1;
150 <      if (ToLower(*m) != ToLower(*n))
151 <      {
152 <        if (!ma)
153 <          return 1;
154 <        m = ma;
155 <        n = ++na;
156 <      }
157 <      else
158 <        m++, n++;
107 >        n++;
108 >        break;
109      }
160    else
161      m++, n++;
110    }
111  
112    return 1;
113   }
114  
167 /* match_chan()
168 *
169 * The match_esc() function doing channel prefix auto-escape,
170 * ie. mask: #blah*blah is seen like \#blah*blah
171 */
172 int
173 match_chan(const char *mask, const char *name)
174 {
175  if (*mask == '#')
176  {
177    if (*name != '#')
178      return 0;
179    ++name, ++mask;
180  }
181
182  return match_esc(mask, name) == 0;
183 }
184
115   /*
116   * collapse()
117   * Collapse a pattern string into minimal components.
# Line 401 | Line 331 | const unsigned int CharAttrs[] = {
331   /* SP */     PRINT_C|SPACE_C,
332   /* ! */      PRINT_C|KWILD_C|CHAN_C|VCHAN_C|NONEOS_C,
333   /* " */      PRINT_C|CHAN_C|VCHAN_C|NONEOS_C,
334 < /* # */      PRINT_C|KWILD_C|MWILD_C|CHANPFX_C|CHAN_C|VCHAN_C|NONEOS_C,
334 > /* # */      PRINT_C|KWILD_C|CHANPFX_C|CHAN_C|VCHAN_C|NONEOS_C,
335   /* $ */      PRINT_C|CHAN_C|VCHAN_C|NONEOS_C|USER_C,
336   /* % */      PRINT_C|CHAN_C|VCHAN_C|NONEOS_C,
337   /* & */      PRINT_C|CHAN_C|VCHAN_C|NONEOS_C,

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)