Home | History | Annotate | Line # | Download | only in global
      1 /*	$NetBSD: been_here.c,v 1.4 2022/10/08 16:12:45 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 /*	int	been_here_drop_fixed(dup_filter, string)
     32 /*	BH_TABLE *dup_filter;
     33 /*	char	*string;
     34 /*
     35 /*	int	been_here_drop(dup_filter, format, ...)
     36 /*	BH_TABLE *dup_filter;
     37 /*	char	*format;
     38 /*
     39 /*	void	been_here_free(dup_filter)
     40 /*	BH_TABLE *dup_filter;
     41 /* DESCRIPTION
     42 /*	This module implements a simple filter to detect repeated
     43 /*	occurrences of character strings.
     44 /*
     45 /*	been_here_init() creates an empty duplicate filter.
     46 /*
     47 /*	been_here_fixed() looks up a fixed string in the given table, and
     48 /*	makes an entry in the table if the string was not found. The result
     49 /*	is non-zero (true) if the string was found, zero (false) otherwise.
     50 /*
     51 /*	been_here() formats its arguments, looks up the result in the
     52 /*	given table, and makes an entry in the table if the string was
     53 /*	not found. The result is non-zero (true) if the formatted result was
     54 /*	found, zero (false) otherwise.
     55 /*
     56 /*	been_here_check_fixed() and been_here_check() are similar
     57 /*	but do not update the duplicate filter.
     58 /*
     59 /*	been_here_drop_fixed() looks up a fixed string in the given
     60 /*	table, and deletes the entry if the string was found. The
     61 /*	result is non-zero (true) if the string was found, zero
     62 /*	(false) otherwise.
     63 /*
     64 /*	been_here_drop() formats its arguments, looks up the result
     65 /*	in the given table, and removes the entry if the formatted
     66 /*	result was found. The result is non-zero (true) if the
     67 /*	formatted result was found, zero (false) otherwise.
     68 /*
     69 /*	been_here_free() releases storage for a duplicate filter.
     70 /*
     71 /*	Arguments:
     72 /* .IP size
     73 /*	Upper bound on the table size; at most \fIsize\fR strings will
     74 /*	be remembered.  Specify BH_BOUND_NONE to disable the upper bound.
     75 /* .IP flags
     76 /*	Requests for special processing. Specify the bitwise OR of zero
     77 /*	or more flags:
     78 /* .RS
     79 /* .IP BH_FLAG_FOLD
     80 /*	Enable case-insensitive lookup.
     81 /* .IP BH_FLAG_NONE
     82 /*	A manifest constant that requests no special processing.
     83 /* .RE
     84 /* .IP dup_filter
     85 /*	The table with remembered names
     86 /* .IP string
     87 /*	Fixed search string.
     88 /* .IP format
     89 /*	Format for building the search string.
     90 /* LICENSE
     91 /* .ad
     92 /* .fi
     93 /*	The Secure Mailer license must be distributed with this software.
     94 /* AUTHOR(S)
     95 /*	Wietse Venema
     96 /*	IBM T.J. Watson Research
     97 /*	P.O. Box 704
     98 /*	Yorktown Heights, NY 10598, USA
     99 /*
    100 /*	Wietse Venema
    101 /*	Google, Inc.
    102 /*	111 8th Avenue
    103 /*	New York, NY 10011, USA
    104 /*--*/
    105 
    106 /* System library. */
    107 
    108 #include "sys_defs.h"
    109 #include <stdlib.h>			/* 44BSD stdarg.h uses abort() */
    110 #include <stdarg.h>
    111 
    112 /* Utility library. */
    113 
    114 #include <msg.h>
    115 #include <mymalloc.h>
    116 #include <htable.h>
    117 #include <vstring.h>
    118 #include <stringops.h>
    119 
    120 /* Global library. */
    121 
    122 #include "been_here.h"
    123 
    124 #define STR(x)	vstring_str(x)
    125 
    126 /* been_here_init - initialize duplicate filter */
    127 
    128 BH_TABLE *been_here_init(int limit, int flags)
    129 {
    130     BH_TABLE *dup_filter;
    131 
    132     dup_filter = (BH_TABLE *) mymalloc(sizeof(*dup_filter));
    133     dup_filter->limit = limit;
    134     dup_filter->flags = flags;
    135     dup_filter->table = htable_create(0);
    136     return (dup_filter);
    137 }
    138 
    139 /* been_here_free - destroy duplicate filter */
    140 
    141 void    been_here_free(BH_TABLE *dup_filter)
    142 {
    143     htable_free(dup_filter->table, (void (*) (void *)) 0);
    144     myfree((void *) dup_filter);
    145 }
    146 
    147 /* been_here - duplicate detector with finer control */
    148 
    149 int     been_here(BH_TABLE *dup_filter, const char *fmt,...)
    150 {
    151     VSTRING *buf = vstring_alloc(100);
    152     int     status;
    153     va_list ap;
    154 
    155     /*
    156      * Construct the string to be checked.
    157      */
    158     va_start(ap, fmt);
    159     vstring_vsprintf(buf, fmt, ap);
    160     va_end(ap);
    161 
    162     /*
    163      * Do the duplicate check.
    164      */
    165     status = been_here_fixed(dup_filter, vstring_str(buf));
    166 
    167     /*
    168      * Cleanup.
    169      */
    170     vstring_free(buf);
    171     return (status);
    172 }
    173 
    174 /* been_here_fixed - duplicate detector */
    175 
    176 int     been_here_fixed(BH_TABLE *dup_filter, const char *string)
    177 {
    178     VSTRING *folded_string;
    179     const char *lookup_key;
    180     int     status;
    181 
    182     /*
    183      * Special processing: case insensitive lookup.
    184      */
    185     if (dup_filter->flags & BH_FLAG_FOLD) {
    186 	folded_string = vstring_alloc(100);
    187 	lookup_key = casefold(folded_string, string);
    188     } else {
    189 	folded_string = 0;
    190 	lookup_key = string;
    191     }
    192 
    193     /*
    194      * Do the duplicate check.
    195      */
    196     if (htable_locate(dup_filter->table, lookup_key) != 0) {
    197 	status = 1;
    198     } else {
    199 	if (dup_filter->limit <= 0
    200 	    || dup_filter->limit > dup_filter->table->used)
    201 	    htable_enter(dup_filter->table, lookup_key, (void *) 0);
    202 	status = 0;
    203     }
    204     if (msg_verbose)
    205 	msg_info("been_here: %s: %d", string, status);
    206 
    207     /*
    208      * Cleanup.
    209      */
    210     if (folded_string)
    211 	vstring_free(folded_string);
    212 
    213     return (status);
    214 }
    215 
    216 /* been_here_check - query duplicate detector with finer control */
    217 
    218 int     been_here_check(BH_TABLE *dup_filter, const char *fmt,...)
    219 {
    220     VSTRING *buf = vstring_alloc(100);
    221     int     status;
    222     va_list ap;
    223 
    224     /*
    225      * Construct the string to be checked.
    226      */
    227     va_start(ap, fmt);
    228     vstring_vsprintf(buf, fmt, ap);
    229     va_end(ap);
    230 
    231     /*
    232      * Do the duplicate check.
    233      */
    234     status = been_here_check_fixed(dup_filter, vstring_str(buf));
    235 
    236     /*
    237      * Cleanup.
    238      */
    239     vstring_free(buf);
    240     return (status);
    241 }
    242 
    243 /* been_here_check_fixed - query duplicate detector */
    244 
    245 int     been_here_check_fixed(BH_TABLE *dup_filter, const char *string)
    246 {
    247     VSTRING *folded_string;
    248     const char *lookup_key;
    249     int     status;
    250 
    251     /*
    252      * Special processing: case insensitive lookup.
    253      */
    254     if (dup_filter->flags & BH_FLAG_FOLD) {
    255 	folded_string = vstring_alloc(100);
    256 	lookup_key = casefold(folded_string, string);
    257     } else {
    258 	folded_string = 0;
    259 	lookup_key = string;
    260     }
    261 
    262     /*
    263      * Do the duplicate check.
    264      */
    265     status = (htable_locate(dup_filter->table, lookup_key) != 0);
    266     if (msg_verbose)
    267 	msg_info("been_here_check: %s: %d", string, status);
    268 
    269     /*
    270      * Cleanup.
    271      */
    272     if (folded_string)
    273 	vstring_free(folded_string);
    274 
    275     return (status);
    276 }
    277 
    278 /* been_here_drop - remove filter entry with finer control */
    279 
    280 int     been_here_drop(BH_TABLE *dup_filter, const char *fmt,...)
    281 {
    282     VSTRING *buf = vstring_alloc(100);
    283     int     status;
    284     va_list ap;
    285 
    286     /*
    287      * Construct the string to be dropped.
    288      */
    289     va_start(ap, fmt);
    290     vstring_vsprintf(buf, fmt, ap);
    291     va_end(ap);
    292 
    293     /*
    294      * Drop the filter entry.
    295      */
    296     status = been_here_drop_fixed(dup_filter, vstring_str(buf));
    297 
    298     /*
    299      * Cleanup.
    300      */
    301     vstring_free(buf);
    302     return (status);
    303 }
    304 
    305 /* been_here_drop_fixed - remove filter entry */
    306 
    307 int     been_here_drop_fixed(BH_TABLE *dup_filter, const char *string)
    308 {
    309     VSTRING *folded_string;
    310     const char *lookup_key;
    311     int     status;
    312 
    313     /*
    314      * Special processing: case insensitive lookup.
    315      */
    316     if (dup_filter->flags & BH_FLAG_FOLD) {
    317 	folded_string = vstring_alloc(100);
    318 	lookup_key = casefold(folded_string, string);
    319     } else {
    320 	folded_string = 0;
    321 	lookup_key = string;
    322     }
    323 
    324     /*
    325      * Drop the filter entry.
    326      */
    327     if ((status = been_here_check_fixed(dup_filter, lookup_key)) != 0)
    328 	htable_delete(dup_filter->table, lookup_key, (void (*) (void *)) 0);
    329 
    330     /*
    331      * Cleanup.
    332      */
    333     if (folded_string)
    334 	vstring_free(folded_string);
    335 
    336     return (status);
    337 }
    338