diff --git a/src/sbbs3/str_util.c b/src/sbbs3/str_util.c
index dac22f2814fece4297eda17ce57cc32276457fca..3cf15f5eab4697dc460e4e4c935b4b6b508bce8f 100644
--- a/src/sbbs3/str_util.c
+++ b/src/sbbs3/str_util.c
@@ -244,64 +244,68 @@ char* strip_char(const char* str, char* dest, char ch)
 }
 
 /****************************************************************************/
-/* Pattern matching string search of 'insearchof' in 'string'.				*/
-/****************************************************************************/
-BOOL findstr_in_string(const char* insearchof, char* string)
-{
+/* Pattern matching string search of 'insearchof' in 'pattern'.				*/
+/* pattern matching is case-insensitive										*/
+/* patterns beginning with ';' are comments (never match)					*/
+/* patterns beginning with '!' are reverse-matched (returns FALSE if match)	*/
+/* patterns ending in '~' will match string anywhere (sub-string search)	*/
+/* patterns ending in '^' will match left string fragment only				*/
+/* patterns including '*' must match both left and right string fragments	*/
+/* all other patterns are exact-match checking								*/
+/****************************************************************************/
+BOOL findstr_in_string(const char* search, const char* pattern)
+{
+	char	buf[256];
 	char*	p;
-	char	str[256];
-	char	search[81];
-	int		c;
-	int		i;
-	BOOL	found=FALSE;
-
-	if(string==NULL || insearchof==NULL)
-		return(FALSE);
+	char*	last;
+	const char*	splat;
+	size_t	len;
+	BOOL	found = FALSE;
 
-	SAFECOPY(search,insearchof);
-	strupr(search);
-	SAFECOPY(str,string);
+	if(pattern == NULL || search == NULL)
+		return FALSE;
 
-	p=str;	
-//	SKIP_WHITESPACE(p);
+	SAFECOPY(buf, pattern);
+	p = buf;
 
-	if(*p==';')		/* comment */
-		return(FALSE);
+	if(*p == ';')		/* comment */
+		return FALSE;
 
-	if(*p=='!')	{	/* !match */
-		found=TRUE;
+	if(*p == '!')	{	/* reverse-match */
+		found = TRUE;
 		p++;
 	}
 
 	truncsp(p);
-	c=strlen(p);
-	if(c) {
-		c--;
-		strupr(p);
-		if(p[c]=='~') {
-			p[c]=0;
-			if(strstr(search,p))
-				found=!found; 
+	len = strlen(p);
+	if(len > 0) {
+		last = p + len - 1;
+		if(*last == '~') {
+			*last = '\0';
+			if(strcasestr(search, p) != NULL)
+				found = !found; 
 		}
 
-		else if(p[c]=='^' || p[c]=='*') {
-			p[c]=0;
-			if(!strncmp(p,search,c))
-				found=!found; 
+		else if(*last == '^') {
+			if(strnicmp(p, search, len - 1) == 0)
+				found = !found; 
 		}
 
-		else if(p[0]=='*') {
-			i=strlen(search);
-			if(i<c)
-				return(found);
-			if(!strncmp(p+1,search+(i-c),c))
-				found=!found; 
+		else if((splat = strchr(p, '*')) != NULL) {
+			int left = splat - p;
+			int right = len - (left + 1);
+			int slen = strlen(search);
+			if(slen < left + right)
+				return found;
+			if(strnicmp(search, p, left) == 0
+				&& strnicmp(p + left + 1, search + (slen - right), right) == 0)
+				found = !found;
 		}
 
-		else if(!strcmp(p,search))
-			found=!found; 
+		else if(stricmp(p, search) == 0)
+			found = !found; 
 	} 
-	return(found);
+	return found;
 }
 
 static uint32_t encode_ipv4_address(unsigned int byte[])
diff --git a/src/sbbs3/str_util.h b/src/sbbs3/str_util.h
index f8dec9b39d09640056d1b043002f3a3089dbe731..010a6ea9dd501a0405b6880c801e6fd123b63561 100644
--- a/src/sbbs3/str_util.h
+++ b/src/sbbs3/str_util.h
@@ -46,7 +46,7 @@ DLLEXPORT char *    replace_named_values(const char* src ,char* buf, size_t bufl
 DLLEXPORT char *	condense_whitespace(char* str);
 DLLEXPORT char		exascii_to_ascii_char(uchar ch);
 DLLEXPORT BOOL		findstr(const char *insearch, const char *fname);
-DLLEXPORT BOOL		findstr_in_string(const char* insearchof, char* string);
+DLLEXPORT BOOL		findstr_in_string(const char* insearchof, const char* pattern);
 DLLEXPORT BOOL		findstr_in_list(const char* insearchof, str_list_t list);
 DLLEXPORT str_list_t findstr_list(const char* fname);
 DLLEXPORT BOOL		trashcan(scfg_t* cfg, const char *insearch, const char *name);