1 /* $NetBSD: been_here.c,v 1.1.1.1 2009/06/23 10:08:45 tron 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 a value <= 0 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 /* 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 (*) (char *)) 0); 119 myfree((char *) 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 char *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 = mystrdup(string); 162 lookup_key = lowercase(folded_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, (char *) 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 myfree(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 char *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 = mystrdup(string); 231 lookup_key = lowercase(folded_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 myfree(folded_string); 249 250 return (status); 251 } 252