summaryrefslogtreecommitdiffstats
path: root/src/global/been_here.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/global/been_here.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/src/global/been_here.c b/src/global/been_here.c
new file mode 100644
index 0000000..d0c6820
--- /dev/null
+++ b/src/global/been_here.c
@@ -0,0 +1,335 @@
+/*++
+/* 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
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, 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);
+}