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