diff -rduN ircd-hybrid-6.0+UniBG-p2/include/client.h ircd-hybrid-6.0+UniBG-p2+spamcheck/include/client.h
--- ircd-hybrid-6.0+UniBG-p2/include/client.h	2001-10-25 07:25:06.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/include/client.h	2003-01-18 14:55:01.000000000 -0200
@@ -67,6 +67,13 @@
 struct Listener;
 struct Client;
 
+#ifdef MSGSPAMCHECK
+struct badwordst {
+  char *word; /* spam word */
+  time_t **timestamps; /* CurrentTimes are stored here */
+};
+#endif
+
 /*
  * Client structures
  */
@@ -81,6 +88,11 @@
   int            joined;        /* number of channels joined */
   char           id[IDLEN + 1]; /* for future use *hint* */
   const char*    server;        /* pointer to scached server name */
+
+#ifdef MSGSPAMCHECK
+  struct badwordst **badword; /* array of badwords */
+#endif
+
   /*
   ** In a perfect world the 'server' name
   ** should not be needed, a pointer to the
diff -rduN ircd-hybrid-6.0+UniBG-p2/include/config.h ircd-hybrid-6.0+UniBG-p2+spamcheck/include/config.h
--- ircd-hybrid-6.0+UniBG-p2/include/config.h	2001-11-17 15:48:03.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/include/config.h	2003-01-18 14:55:01.000000000 -0200
@@ -271,6 +271,18 @@
 
 /* ------========== End of UniBG Network additions ==========------ */
 
+/* ------========= Start of IRCHelp additions =========------*/
+
+/*
+ * If a user says a message containing the word m n time this will be
+ * written in the locops. (n and m are defined in the conf file with W: lines)
+ * #undef this to remove the spam check. --special thanks to famzah
+ */
+#define MSGSPAMCHECK
+
+// naf naf scream
+/* ------========= End of IRCHelp additions =========------*/
+
 /* TS_MAX_DELTA and TS_WARN_DELTA -  allowed delta for TS when another
  * server connects.
  *
diff -rduN ircd-hybrid-6.0+UniBG-p2/include/ircd.h ircd-hybrid-6.0+UniBG-p2+spamcheck/include/ircd.h
--- ircd-hybrid-6.0+UniBG-p2/include/ircd.h	2001-01-04 13:23:09.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/include/ircd.h	2003-01-18 14:55:01.000000000 -0200
@@ -145,7 +145,9 @@
 #ifdef REJECT_HOLD
 extern int reject_held_fds;
 #endif
-
+#ifdef MSGSPAMCHECK
+int spammemory;
+#endif
 extern size_t   get_maxrss(void);
 
 /* 1800 == half an hour
diff -rduN ircd-hybrid-6.0+UniBG-p2/include/list.h ircd-hybrid-6.0+UniBG-p2+spamcheck/include/list.h
--- ircd-hybrid-6.0+UniBG-p2/include/list.h	1999-07-28 00:42:12.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/include/list.h	2003-01-18 14:55:45.000000000 -0200
@@ -33,6 +33,9 @@
 struct User;
 struct Channel;
 
+#ifdef MSGSPAMCHECK
+extern int count_w_lines(void);
+#endif
 extern void count_user_memory(int *, int *);
 extern void count_links_memory(int *, int *);
 extern void count_flud_memory(int *, int *);
diff -rduN ircd-hybrid-6.0+UniBG-p2/include/s_conf.h ircd-hybrid-6.0+UniBG-p2+spamcheck/include/s_conf.h
--- ircd-hybrid-6.0+UniBG-p2/include/s_conf.h	2001-10-24 22:28:17.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/include/s_conf.h	2003-01-18 14:55:01.000000000 -0200
@@ -267,6 +267,9 @@
 #ifdef OPERSPOOF
 #define CONF_VLINE              0x400000
 #endif
+#ifdef MSGSPAMCHECK
+#define CONF_WLINE              0x800000
+#endif
 
 #define CONF_OPS                (CONF_OPERATOR | CONF_LOCOP)
 #define CONF_SERVER_MASK        (CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER)
@@ -361,6 +364,11 @@
 extern struct ConfItem *r_conf;
 #endif
 
+#ifdef MSGSPAMCHECK
+/* conf wline link list root */
+extern struct ConfItem *w_conf;
+#endif
+
 #ifdef OPERSPOOF
 /* conf vline link list root */
 extern struct ConfItem *v_conf;
@@ -414,6 +422,9 @@
 extern struct ConfItem* find_conf_by_name(const char* name, int status);
 extern struct ConfItem* find_conf_by_host(const char* host, int status);
 extern struct ConfItem* find_kill (struct Client *);
+#ifdef MSGSPAMCHECK
+extern struct ConfItem* find_w_line(char *);
+#endif
 extern int conf_connect_allowed(struct in_addr addr);
 extern char *oper_flags_as_string(int);
 extern char *oper_privs_as_string(struct Client *, int);
diff -rduN ircd-hybrid-6.0+UniBG-p2/src/ircd.c ircd-hybrid-6.0+UniBG-p2+spamcheck/src/ircd.c
--- ircd-hybrid-6.0+UniBG-p2/src/ircd.c	2001-01-04 13:23:09.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/src/ircd.c	2003-01-18 14:55:01.000000000 -0200
@@ -119,7 +119,9 @@
 extern time_t server_split_time;
 extern int    server_was_split;
 #endif
-
+#ifdef MSGSPAMCHECK
+int spammemory = 0;
+#endif
 int cold_start = YES;   /* set if the server has just fired up */
 
 /* /quote set variables */
diff -rduN ircd-hybrid-6.0+UniBG-p2/src/list.c ircd-hybrid-6.0+UniBG-p2+spamcheck/src/list.c
--- ircd-hybrid-6.0+UniBG-p2/src/list.c	2000-11-18 17:11:11.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/src/list.c	2003-01-18 14:55:01.000000000 -0200
@@ -36,7 +36,10 @@
 #include "s_log.h"
 #include "send.h"
 #include "flud.h"
-
+#ifdef MSGSPAMCHECK
+#include "s_conf.h"
+#include "ircd.h"
+#endif
 #include <string.h>
 #include <stdlib.h>
 
@@ -141,6 +144,11 @@
       user->channel = NULL;
       user->invited = NULL;
       cptr->user = user;
+#ifdef MSGSPAMCHECK
+	  user->badword = (struct badwordst **)MyMalloc(sizeof(struct badwordst *)*count_w_lines());
+	  spammemory += sizeof(struct badwordst *)*count_w_lines();
+	  memset(user->badword, 0, sizeof(struct badwordst *)*count_w_lines());
+#endif
     }
   return user;
 }
@@ -177,6 +185,11 @@
 */
 void _free_user(anUser* user, aClient* cptr)
 {
+#ifdef MSGSPAMCHECK
+  int i, j;
+  struct ConfItem *wlineentry;
+#endif
+
   if (--user->refcnt <= 0)
     {
       if (user->away)
@@ -191,7 +204,23 @@
                  cptr->username, cptr->host, user,
                  user->invited, user->channel, user->joined,
                  user->refcnt);
-
+#ifdef MSGSPAMCHECK
+	  for (i = 0; i < count_w_lines(); i++) {
+		if (user->badword[i] == NULL) {
+		  break;
+		} else {
+		  wlineentry = find_w_line(user->badword[i]->word);
+		  if (wlineentry == NULL) {
+			for (j = 0; j < atoi(wlineentry->user); j++) {
+			  free(((user->badword[i])->timestamps)[j]);
+			}
+			free(((user->badword[i])->timestamps));
+		  }
+		}
+		free(user->badword[i]);
+	  }
+	  free(user->badword);
+#endif
       if(BlockHeapFree(free_anUsers,user))
         {
           sendto_realops("list.c couldn't BlockHeapFree(free_anUsers,user) user = %lX", user );
@@ -316,3 +345,28 @@
 }
 #endif
 
+#ifdef MSGSPAMCHECK
+/*
+ * count_w_lines
+ *
+ * inputs       - nothing
+ * output       - number of w_lines
+ * side effects - counts w lines
+ *
+ */
+
+extern int count_w_lines (void)
+{
+  struct ConfItem *aconf;
+  int lines = 0;
+
+  for (aconf = w_conf; aconf; aconf = aconf->next)
+  {
+	if (BadPtr(aconf->host) || BadPtr(aconf->passwd) || BadPtr(aconf->user))
+	  continue;
+
+	lines++;
+  }
+  return lines;
+}
+#endif
diff -rduN ircd-hybrid-6.0+UniBG-p2/src/m_message.c ircd-hybrid-6.0+UniBG-p2+spamcheck/src/m_message.c
--- ircd-hybrid-6.0+UniBG-p2/src/m_message.c	2001-11-17 13:26:25.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/src/m_message.c	2003-01-18 14:55:01.000000000 -0200
@@ -35,9 +35,12 @@
 #include "irc_string.h"
 #include "hash.h"
 #include "class.h"
-#ifdef DCCFILECHECK
+#if defined(DCCFILECHECK) || defined(MSGSPAMCHECK)
 #include "s_conf.h"
 #endif
+#ifdef MSGSPAMCHECK
+#include "list.h"
+#endif
 
 #include <string.h>
 
@@ -46,6 +49,10 @@
 int check_for_dccsend(char *str);
 int find_r_line(char *fileexttofind);
 #endif
+#ifdef MSGSPAMCHECK
+void clean_ts(time_t **, int, int);
+struct ConfItem* find_w_line(char *);
+#endif
 
 int msg_has_colors(char *msg);
 
@@ -125,6 +132,10 @@
                           char *parv[],
                           int notice)
 {
+#ifdef MSGSPAMCHECK
+  struct ConfItem *wlineentry;
+  int i, j;
+#endif
   struct Client       *acptr;
   char  *s;
   struct Channel *chptr;
@@ -147,6 +158,46 @@
       return -1;
     }
 
+#ifdef MSGSPAMCHECK
+  wlineentry = find_w_line(parv[2]);
+
+  if (wlineentry != NULL)
+  {
+	for (i = 0; i < count_w_lines(); i++) {
+	  if (cptr->user->badword[i] != NULL) {
+		if (!irccmp(cptr->user->badword[i]->word, wlineentry->host)) {
+		  clean_ts((cptr->user->badword[i])->timestamps, atoi(wlineentry->passwd), atoi(wlineentry->user));
+		  for (j = 0; j < atoi(wlineentry->user); j++) {
+			if (BadPtr((cptr->user->badword[i])->timestamps[j])) {
+			  ((cptr->user->badword[i])->timestamps)[j] = (time_t *)MyMalloc(sizeof(time_t));
+			  spammemory += sizeof(time_t);
+			  *(((cptr->user->badword[i])->timestamps)[j]) = CurrentTime;
+			  break;
+			}
+		  }
+
+		  if (j == (atoi(wlineentry->user) - 1))
+			sendto_realops("Spam from %s!%s@%s detected, message \"%s\", containing the masked word \"%s\" defined as a badword in my list.",
+			  			  cptr->name, cptr->username, cptr->host, parv[2], wlineentry->host);
+		  break;
+		}
+	  } else {
+		cptr->user->badword[i]=(struct badwordst *)MyMalloc(sizeof(struct badwordst));
+		spammemory += sizeof(struct badwordst);
+		memset(cptr->user->badword[i], 0, sizeof(struct badwordst));
+		(cptr->user->badword[i])->word = wlineentry->host;
+		(cptr->user->badword[i])->timestamps=(time_t **)MyMalloc(sizeof(time_t *)*atoi(wlineentry->user));
+		spammemory += sizeof(time_t *)*atoi(wlineentry->user);
+		memset((cptr->user->badword[0])->timestamps, 0, sizeof(time_t *)*atoi(wlineentry->user));
+		((cptr->user->badword[i])->timestamps)[0]=(time_t *)MyMalloc(sizeof(time_t));
+		spammemory += sizeof(time_t);
+		*(((cptr->user->badword[i])->timestamps)[0])=CurrentTime;
+		break;
+	  }
+	}
+  }
+#endif
+
   if (MyConnect(sptr))
     {
 #ifdef ANTI_SPAMBOT
@@ -671,6 +722,28 @@
 }
 #endif /* DCCFILECHECK */
 
+#ifdef MSGSPAMCHECK
+void clean_ts(time_t **timestamps, int times, int elements)
+{
+  int i, index=-1;
+
+  for (i = 0; i < elements; i++) {
+	if (BadPtr(timestamps[i])) {
+	  if (index == -1)
+		index = i;
+	} else if (CurrentTime - *timestamps[i] > times) {
+	  timestamps[i] = NULL;
+	} else {
+	  if (index != -1) {
+		timestamps[index] = timestamps[i];
+		timestamps[i] = NULL;
+		index++;
+	  }
+	}
+  }
+}
+#endif /* MSGSPAMCHECK */
+
 /* check to see if the message has any color chars in it. */
 int msg_has_colors(char *msg)
 {
diff -rduN ircd-hybrid-6.0+UniBG-p2/src/s_conf.c ircd-hybrid-6.0+UniBG-p2+spamcheck/src/s_conf.c
--- ircd-hybrid-6.0+UniBG-p2/src/s_conf.c	2001-11-17 15:34:56.000000000 -0200
+++ ircd-hybrid-6.0+UniBG-p2+spamcheck/src/s_conf.c	2003-01-18 14:55:01.000000000 -0200
@@ -145,6 +145,12 @@
 static void clear_r_lines(void);
 #endif
 
+#ifdef MSGSPAMCHECK
+/* conf wline link list root */
+extern struct ConfItem *find_w_conf(char *);
+struct ConfItem        *w_conf = ((struct ConfItem *)NULL);
+#endif
+
 #ifdef OPERSPOOF
 /* conf vline link list root */
 struct ConfItem        *v_conf = ((struct ConfItem *)NULL);
@@ -2093,6 +2099,12 @@
 	  aconf->status = CONF_VLINE;
 	  break;
 #endif
+#ifdef MSGSPAMCHECK
+        case 'W': /* spam words */
+        case 'w':
+          aconf->status = CONF_WLINE;
+          break;
+#endif
 
         case 'X': /* rejected gecos */
         case 'x': 
@@ -2486,6 +2498,14 @@
           r_conf = aconf;
         }
 #endif
+#ifdef MSGSPAMCHECK
+       else if (aconf->status & CONF_WLINE)
+        {
+          dontadd = 1;
+          aconf->next = w_conf;
+          w_conf = aconf;
+        }
+#endif
 #ifdef OPERSPOOF
       else if (aconf->status & CONF_VLINE)
        {
@@ -3597,6 +3617,43 @@
 
   do_include_conf();
 
+#ifdef MSGSPAMCHECK
+  if (!cold)
+  {
+	register aClient *cptr;
+	int i, j;
+	struct ConfItem *wlineentry;
+
+	for (cptr = local_cptr_list; cptr; cptr = cptr->next_local_client)
+	{
+	  if (!cptr)
+		continue;
+
+	  if (!cptr->user)
+		continue;
+
+	  for (i = 0; i < count_w_lines(); i++) {
+		if (cptr->user->badword[i] == NULL) {
+		  break;
+		} else {
+		  wlineentry = find_w_line(cptr->user->badword[i]->word);
+		  if (wlineentry != NULL) {
+        	for (j = 0; j < atoi(wlineentry->user); j++) {
+	      	  free(((cptr->user->badword[i])->timestamps)[j]);
+	        }
+	        free(((cptr->user->badword[i])->timestamps));
+		  }
+	    }
+        free(cptr->user->badword[i]);
+	  }
+	  free(cptr->user->badword);
+      cptr->user->badword = (struct badwordst **)MyMalloc(sizeof(struct badwordst *)*count_w_lines());
+      spammemory += sizeof(struct badwordst *)*count_w_lines();
+      memset(cptr->user->badword, 0, sizeof(struct badwordst *)*count_w_lines());
+	}
+  }	
+#endif
+  
   /* ZZZ have to deal with single ircd.conf situations */
   /* It would be better to check for NULL return from filename 
    * or *filename == '\0'; and then just ignoring it 
@@ -3963,4 +4020,30 @@
     }
   return NO;
 }
-#endif
\ No newline at end of file
+#endif
+
+#ifdef MSGSPAMCHECK
+/*
+ * find_w_line
+ *
+ * inputs       - msg from privmsg
+ * output       - pointer to the w_line struct if found, 0 if not found
+ * side effects - looks for matches on W lined spam masked words
+ * thanks to decho
+ */
+
+extern struct ConfItem* find_w_line(char *spamwordtofind)
+{
+  struct ConfItem *aconf;
+
+  for (aconf = w_conf; aconf; aconf = aconf->next)
+  {
+	if (BadPtr(aconf->host) || BadPtr(aconf->passwd) || BadPtr(aconf->user))
+	  continue;
+
+    if (match(aconf->host, spamwordtofind))
+      return aconf;
+  }
+  return NULL;
+}
+#endif
