Postfix3.3.1
been_here.c
[詳解]
1 /*++
2 /* NAME
3 /* been_here 3
4 /* SUMMARY
5 /* detect repeated occurrence of string
6 /* SYNOPSIS
7 /* #include <been_here.h>
8 /*
9 /* BH_TABLE *been_here_init(size, flags)
10 /* int size;
11 /* int flags;
12 /*
13 /* int been_here_fixed(dup_filter, string)
14 /* BH_TABLE *dup_filter;
15 /* char *string;
16 /*
17 /* int been_here(dup_filter, format, ...)
18 /* BH_TABLE *dup_filter;
19 /* char *format;
20 /*
21 /* int been_here_check_fixed(dup_filter, string)
22 /* BH_TABLE *dup_filter;
23 /* char *string;
24 /*
25 /* int been_here_check(dup_filter, format, ...)
26 /* BH_TABLE *dup_filter;
27 /* char *format;
28 /*
29 /* void been_here_free(dup_filter)
30 /* BH_TABLE *dup_filter;
31 /* DESCRIPTION
32 /* This module implements a simple filter to detect repeated
33 /* occurrences of character strings.
34 /*
35 /* been_here_init() creates an empty duplicate filter.
36 /*
37 /* been_here_fixed() looks up a fixed string in the given table, and
38 /* makes an entry in the table if the string was not found. The result
39 /* is non-zero (true) if the string was found, zero (false) otherwise.
40 /*
41 /* been_here() formats its arguments, looks up the result in the
42 /* given table, and makes an entry in the table if the string was
43 /* not found. The result is non-zero (true) if the formatted result was
44 /* found, zero (false) otherwise.
45 /*
46 /* been_here_check_fixed() and been_here_check() are similar
47 /* but do not update the duplicate filter.
48 /*
49 /* been_here_free() releases storage for a duplicate filter.
50 /*
51 /* Arguments:
52 /* .IP size
53 /* Upper bound on the table size; at most \fIsize\fR strings will
54 /* be remembered. Specify a value <= 0 to disable the upper bound.
55 /* .IP flags
56 /* Requests for special processing. Specify the bitwise OR of zero
57 /* or more flags:
58 /* .RS
59 /* .IP BH_FLAG_FOLD
60 /* Enable case-insensitive lookup.
61 /* .IP BH_FLAG_NONE
62 /* A manifest constant that requests no special processing.
63 /* .RE
64 /* .IP dup_filter
65 /* The table with remembered names
66 /* .IP string
67 /* Fixed search string.
68 /* .IP format
69 /* Format for building the search string.
70 /* LICENSE
71 /* .ad
72 /* .fi
73 /* The Secure Mailer license must be distributed with this software.
74 /* AUTHOR(S)
75 /* Wietse Venema
76 /* IBM T.J. Watson Research
77 /* P.O. Box 704
78 /* Yorktown Heights, NY 10598, USA
79 /*--*/
80 
81 /* System library. */
82 
83 #include "sys_defs.h"
84 #include <stdlib.h> /* 44BSD stdarg.h uses abort() */
85 #include <stdarg.h>
86 
87 /* Utility library. */
88 
89 #include <msg.h>
90 #include <mymalloc.h>
91 #include <htable.h>
92 #include <vstring.h>
93 #include <stringops.h>
94 
95 /* Global library. */
96 
97 #include "been_here.h"
98 
99 #define STR(x) vstring_str(x)
100 
101 /* been_here_init - initialize duplicate filter */
102 
103 BH_TABLE *been_here_init(int limit, int flags)
104 {
105  BH_TABLE *dup_filter;
106 
107  dup_filter = (BH_TABLE *) mymalloc(sizeof(*dup_filter));
108  dup_filter->limit = limit;
109  dup_filter->flags = flags;
110  dup_filter->table = htable_create(0);
111  return (dup_filter);
112 }
113 
114 /* been_here_free - destroy duplicate filter */
115 
116 void been_here_free(BH_TABLE *dup_filter)
117 {
118  htable_free(dup_filter->table, (void (*) (void *)) 0);
119  myfree((void *) dup_filter);
120 }
121 
122 /* been_here - duplicate detector with finer control */
123 
124 int been_here(BH_TABLE *dup_filter, const char *fmt,...)
125 {
126  VSTRING *buf = vstring_alloc(100);
127  int status;
128  va_list ap;
129 
130  /*
131  * Construct the string to be checked.
132  */
133  va_start(ap, fmt);
134  vstring_vsprintf(buf, fmt, ap);
135  va_end(ap);
136 
137  /*
138  * Do the duplicate check.
139  */
140  status = been_here_fixed(dup_filter, vstring_str(buf));
141 
142  /*
143  * Cleanup.
144  */
145  vstring_free(buf);
146  return (status);
147 }
148 
149 /* been_here_fixed - duplicate detector */
150 
151 int been_here_fixed(BH_TABLE *dup_filter, const char *string)
152 {
153  VSTRING *folded_string;
154  const char *lookup_key;
155  int status;
156 
157  /*
158  * Special processing: case insensitive lookup.
159  */
160  if (dup_filter->flags & BH_FLAG_FOLD) {
161  folded_string = vstring_alloc(100);
162  lookup_key = casefold(folded_string, string);
163  } else {
164  folded_string = 0;
165  lookup_key = string;
166  }
167 
168  /*
169  * Do the duplicate check.
170  */
171  if (htable_locate(dup_filter->table, lookup_key) != 0) {
172  status = 1;
173  } else {
174  if (dup_filter->limit <= 0
175  || dup_filter->limit > dup_filter->table->used)
176  htable_enter(dup_filter->table, lookup_key, (void *) 0);
177  status = 0;
178  }
179  if (msg_verbose)
180  msg_info("been_here: %s: %d", string, status);
181 
182  /*
183  * Cleanup.
184  */
185  if (folded_string)
186  vstring_free(folded_string);
187 
188  return (status);
189 }
190 
191 /* been_here_check - query duplicate detector with finer control */
192 
193 int been_here_check(BH_TABLE *dup_filter, const char *fmt,...)
194 {
195  VSTRING *buf = vstring_alloc(100);
196  int status;
197  va_list ap;
198 
199  /*
200  * Construct the string to be checked.
201  */
202  va_start(ap, fmt);
203  vstring_vsprintf(buf, fmt, ap);
204  va_end(ap);
205 
206  /*
207  * Do the duplicate check.
208  */
209  status = been_here_check_fixed(dup_filter, vstring_str(buf));
210 
211  /*
212  * Cleanup.
213  */
214  vstring_free(buf);
215  return (status);
216 }
217 
218 /* been_here_check_fixed - query duplicate detector */
219 
220 int been_here_check_fixed(BH_TABLE *dup_filter, const char *string)
221 {
222  VSTRING *folded_string;
223  const char *lookup_key;
224  int status;
225 
226  /*
227  * Special processing: case insensitive lookup.
228  */
229  if (dup_filter->flags & BH_FLAG_FOLD) {
230  folded_string = vstring_alloc(100);
231  lookup_key = casefold(folded_string, string);
232  } else {
233  folded_string = 0;
234  lookup_key = string;
235  }
236 
237  /*
238  * Do the duplicate check.
239  */
240  status = (htable_locate(dup_filter->table, lookup_key) != 0);
241  if (msg_verbose)
242  msg_info("been_here_check: %s: %d", string, status);
243 
244  /*
245  * Cleanup.
246  */
247  if (folded_string)
248  vstring_free(folded_string);
249 
250  return (status);
251 }
int msg_verbose
Definition: msg.c:177
void htable_free(HTABLE *table, void(*free_fn)(void *))
Definition: htable.c:287
#define BH_FLAG_FOLD
Definition: been_here.h:29
void myfree(void *ptr)
Definition: mymalloc.c:207
HTABLE_INFO * htable_locate(HTABLE *table, const char *key)
Definition: htable.c:242
void been_here_free(BH_TABLE *dup_filter)
Definition: been_here.c:116
#define vstring_str(vp)
Definition: vstring.h:71
ssize_t used
Definition: htable.h:27
BH_TABLE * been_here_init(int limit, int flags)
Definition: been_here.c:103
int been_here_check_fixed(BH_TABLE *dup_filter, const char *string)
Definition: been_here.c:220
#define casefold(dst, src)
Definition: stringops.h:67
int const char * fmt
HTABLE * htable_create(ssize_t size)
Definition: htable.c:179
VSTRING * vstring_vsprintf(VSTRING *vp, const char *format, va_list ap)
Definition: vstring.c:614
int been_here(BH_TABLE *dup_filter, const char *fmt,...)
Definition: been_here.c:124
int flags
Definition: been_here.h:24
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
int limit
Definition: been_here.h:23
int been_here_check(BH_TABLE *dup_filter, const char *fmt,...)
Definition: been_here.c:193
int been_here_fixed(BH_TABLE *dup_filter, const char *string)
Definition: been_here.c:151
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
struct HTABLE * table
Definition: been_here.h:25
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
Definition: htable.c:212
void msg_info(const char *fmt,...)
Definition: msg.c:199