diff options
Diffstat (limited to 'src/global/been_here.c')
-rw-r--r-- | src/global/been_here.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/src/global/been_here.c b/src/global/been_here.c new file mode 100644 index 0000000..8147829 --- /dev/null +++ b/src/global/been_here.c @@ -0,0 +1,330 @@ +/*++ +/* NAME +/* been_here 3 +/* SUMMARY +/* detect repeated occurrence of string +/* SYNOPSIS +/* #include <been_here.h> +/* +/* BH_TABLE *been_here_init(size, flags) +/* int size; +/* int flags; +/* +/* int been_here_fixed(dup_filter, string) +/* BH_TABLE *dup_filter; +/* char *string; +/* +/* int been_here(dup_filter, format, ...) +/* BH_TABLE *dup_filter; +/* char *format; +/* +/* int been_here_check_fixed(dup_filter, string) +/* BH_TABLE *dup_filter; +/* char *string; +/* +/* int been_here_check(dup_filter, format, ...) +/* BH_TABLE *dup_filter; +/* char *format; +/* +/* int been_here_drop_fixed(dup_filter, string) +/* BH_TABLE *dup_filter; +/* char *string; +/* +/* int been_here_drop(dup_filter, format, ...) +/* BH_TABLE *dup_filter; +/* char *format; +/* +/* void been_here_free(dup_filter) +/* BH_TABLE *dup_filter; +/* DESCRIPTION +/* This module implements a simple filter to detect repeated +/* occurrences of character strings. +/* +/* been_here_init() creates an empty duplicate filter. +/* +/* been_here_fixed() looks up a fixed string in the given table, and +/* makes an entry in the table if the string was not found. The result +/* is non-zero (true) if the string was found, zero (false) otherwise. +/* +/* been_here() formats its arguments, looks up the result in the +/* given table, and makes an entry in the table if the string was +/* not found. The result is non-zero (true) if the formatted result was +/* found, zero (false) otherwise. +/* +/* been_here_check_fixed() and been_here_check() are similar +/* but do not update the duplicate filter. +/* +/* been_here_drop_fixed() looks up a fixed string in the given +/* table, and deletes the entry if the string was found. The +/* result is non-zero (true) if the string was found, zero +/* (false) otherwise. +/* +/* been_here_drop() formats its arguments, looks up the result +/* in the given table, and removes the entry if the formatted +/* result was found. The result is non-zero (true) if the +/* formatted result was found, zero (false) otherwise. +/* +/* been_here_free() releases storage for a duplicate filter. +/* +/* Arguments: +/* .IP size +/* Upper bound on the table size; at most \fIsize\fR strings will +/* be remembered. Specify BH_BOUND_NONE to disable the upper bound. +/* .IP flags +/* Requests for special processing. Specify the bitwise OR of zero +/* or more flags: +/* .RS +/* .IP BH_FLAG_FOLD +/* Enable case-insensitive lookup. +/* .IP BH_FLAG_NONE +/* A manifest constant that requests no special processing. +/* .RE +/* .IP dup_filter +/* The table with remembered names +/* .IP string +/* Fixed search string. +/* .IP format +/* Format for building the search string. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include "sys_defs.h" +#include <stdlib.h> /* 44BSD stdarg.h uses abort() */ +#include <stdarg.h> + +/* Utility library. */ + +#include <msg.h> +#include <mymalloc.h> +#include <htable.h> +#include <vstring.h> +#include <stringops.h> + +/* Global library. */ + +#include "been_here.h" + +#define STR(x) vstring_str(x) + +/* been_here_init - initialize duplicate filter */ + +BH_TABLE *been_here_init(int limit, int flags) +{ + BH_TABLE *dup_filter; + + dup_filter = (BH_TABLE *) mymalloc(sizeof(*dup_filter)); + dup_filter->limit = limit; + dup_filter->flags = flags; + dup_filter->table = htable_create(0); + return (dup_filter); +} + +/* been_here_free - destroy duplicate filter */ + +void been_here_free(BH_TABLE *dup_filter) +{ + htable_free(dup_filter->table, (void (*) (void *)) 0); + myfree((void *) dup_filter); +} + +/* been_here - duplicate detector with finer control */ + +int been_here(BH_TABLE *dup_filter, const char *fmt,...) +{ + VSTRING *buf = vstring_alloc(100); + int status; + va_list ap; + + /* + * Construct the string to be checked. + */ + va_start(ap, fmt); + vstring_vsprintf(buf, fmt, ap); + va_end(ap); + + /* + * Do the duplicate check. + */ + status = been_here_fixed(dup_filter, vstring_str(buf)); + + /* + * Cleanup. + */ + vstring_free(buf); + return (status); +} + +/* been_here_fixed - duplicate detector */ + +int been_here_fixed(BH_TABLE *dup_filter, const char *string) +{ + VSTRING *folded_string; + const char *lookup_key; + int status; + + /* + * Special processing: case insensitive lookup. + */ + if (dup_filter->flags & BH_FLAG_FOLD) { + folded_string = vstring_alloc(100); + lookup_key = casefold(folded_string, string); + } else { + folded_string = 0; + lookup_key = string; + } + + /* + * Do the duplicate check. + */ + if (htable_locate(dup_filter->table, lookup_key) != 0) { + status = 1; + } else { + if (dup_filter->limit <= 0 + || dup_filter->limit > dup_filter->table->used) + htable_enter(dup_filter->table, lookup_key, (void *) 0); + status = 0; + } + if (msg_verbose) + msg_info("been_here: %s: %d", string, status); + + /* + * Cleanup. + */ + if (folded_string) + vstring_free(folded_string); + + return (status); +} + +/* been_here_check - query duplicate detector with finer control */ + +int been_here_check(BH_TABLE *dup_filter, const char *fmt,...) +{ + VSTRING *buf = vstring_alloc(100); + int status; + va_list ap; + + /* + * Construct the string to be checked. + */ + va_start(ap, fmt); + vstring_vsprintf(buf, fmt, ap); + va_end(ap); + + /* + * Do the duplicate check. + */ + status = been_here_check_fixed(dup_filter, vstring_str(buf)); + + /* + * Cleanup. + */ + vstring_free(buf); + return (status); +} + +/* been_here_check_fixed - query duplicate detector */ + +int been_here_check_fixed(BH_TABLE *dup_filter, const char *string) +{ + VSTRING *folded_string; + const char *lookup_key; + int status; + + /* + * Special processing: case insensitive lookup. + */ + if (dup_filter->flags & BH_FLAG_FOLD) { + folded_string = vstring_alloc(100); + lookup_key = casefold(folded_string, string); + } else { + folded_string = 0; + lookup_key = string; + } + + /* + * Do the duplicate check. + */ + status = (htable_locate(dup_filter->table, lookup_key) != 0); + if (msg_verbose) + msg_info("been_here_check: %s: %d", string, status); + + /* + * Cleanup. + */ + if (folded_string) + vstring_free(folded_string); + + return (status); +} + +/* been_here_drop - remove filter entry with finer control */ + +int been_here_drop(BH_TABLE *dup_filter, const char *fmt,...) +{ + VSTRING *buf = vstring_alloc(100); + int status; + va_list ap; + + /* + * Construct the string to be dropped. + */ + va_start(ap, fmt); + vstring_vsprintf(buf, fmt, ap); + va_end(ap); + + /* + * Drop the filter entry. + */ + status = been_here_drop_fixed(dup_filter, vstring_str(buf)); + + /* + * Cleanup. + */ + vstring_free(buf); + return (status); +} + +/* been_here_drop_fixed - remove filter entry */ + +int been_here_drop_fixed(BH_TABLE *dup_filter, const char *string) +{ + VSTRING *folded_string; + const char *lookup_key; + int status; + + /* + * Special processing: case insensitive lookup. + */ + if (dup_filter->flags & BH_FLAG_FOLD) { + folded_string = vstring_alloc(100); + lookup_key = casefold(folded_string, string); + } else { + folded_string = 0; + lookup_key = string; + } + + /* + * Drop the filter entry. + */ + if ((status = been_here_check_fixed(dup_filter, lookup_key)) != 0) + htable_delete(dup_filter->table, lookup_key, (void (*) (void *)) 0); + + /* + * Cleanup. + */ + if (folded_string) + vstring_free(folded_string); + + return (status); +} |