diff -urNp irc2.10.3p7+hemp2/common/struct_def.h irc2.10.3p7+hemp2+fic/common/struct_def.h
--- irc2.10.3p7+hemp2/common/struct_def.h	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/common/struct_def.h	Thu Aug 26 23:31:55 2004
@@ -186,7 +186,12 @@ typedef struct        LineItem aExtData;
 
 #endif
 #define	SEND_UMODES	(FLAGS_INVISIBLE|FLAGS_OPER|FLAGS_WALLOP|FLAGS_AWAY)
-#define	ALL_UMODES	(SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED)
+#ifdef IGNORE_STRANGERS
+# define FLAGS_CMODE      0x40000 /* user is ignoring strangers */
+# define ALL_UMODES      (SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED|FLAGS_CMODE)
+#else
+# define ALL_UMODES      (SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED)
+#endif
 
 /*
  * flags macros.
@@ -240,6 +245,10 @@ typedef struct        LineItem aExtData;
 #ifdef ILINE_FLAGS
 #define IsKlineExempt(x)	((x)->user && (x)->user->flags & FLAGS_EXEMPT)
 #endif
+#ifdef IGNORE_STRANGERS
+#define IsIgnoringStrangers(x)  ((x)->user && (x)->user->flags & FLAGS_CMODE)
+#endif
+
 /*
  * defined debugging levels
  */
@@ -327,6 +336,9 @@ struct	ConfItem	{
 #define	CONF_BOUNCE		0x040000
 #define	CONF_OTHERKILL		0x080000
 #define	CONF_DENY		0x100000
+#ifdef W_LINE
+#define        CONF_WEB                0x200000
+#endif
 
 #define	CONF_OPS		(CONF_OPERATOR | CONF_LOCOP)
 #define	CONF_SERVER_MASK	(CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER |\
diff -urNp irc2.10.3p7+hemp2/common/support.c irc2.10.3p7+hemp2+fic/common/support.c
--- irc2.10.3p7+hemp2/common/support.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/common/support.c	Thu Aug 26 23:31:55 2004
@@ -861,7 +861,7 @@ char *make_version()
 		sprintf(ver + strlen(ver), "%c%d", DEVLEVEL, dv);
 	if (pl)	/* patchlevel */
 		sprintf(ver + strlen(ver), "p%d", pl);
-	strcat(ver,"+hemp2");
+	strcat(ver,"+hemp2+fic");
 	return mystrdup(ver);
 }
 #ifndef CLIENTCOMPILE
diff -urNp irc2.10.3p7+hemp2/contrib/tkserv/README irc2.10.3p7+hemp2+fic/contrib/tkserv/README
--- irc2.10.3p7+hemp2/contrib/tkserv/README	Tue Jan  4 16:30:21 2000
+++ irc2.10.3p7+hemp2+fic/contrib/tkserv/README	Thu Aug 26 23:31:55 2004
@@ -63,7 +63,7 @@ B) Editing the configuration file (tkcon
 
    TKSERV_ADMIN_NAME (your real name)
    TKSERV_ADMIN_CONTACT (mail address)
-   TKSERV_ADMIN_OTHER (your nick, for example)
+   TKSERV_ADMIN_OTHER (your nick, for example - optional)
 
    TKSERV_NAME (the name of the service appearing on /SERVLIST)
    TKSERV_DESC (a neato description :)
@@ -86,11 +86,8 @@ B) Editing the configuration file (tkcon
 
    TKSERV_DEBUG (for debugging only, displays traffic to standard output)
 
-   TKSERV_IRCD_CONFIG_BAK (the suffix after CPATH for the backup file 
-                          of the ircd.conf file)
-
-   TKSERV_IRCD_CONFIG_TMP (the suffix after CPATH for the temporary copy
-                          of the ircd.conf file) 
+   TKLINE_PATH_BAK (the path of the backup file of the ircd.conf or kline file)
+   TKLINE_PATH_TMP (the path of the temporary copy of the ircd.conf or kline file)
   
 C) Compiling the source
 
diff -urNp irc2.10.3p7+hemp2/contrib/tkserv/tkserv.c irc2.10.3p7+hemp2+fic/contrib/tkserv/tkserv.c
--- irc2.10.3p7+hemp2/contrib/tkserv/tkserv.c	Fri Mar  9 14:55:38 2001
+++ irc2.10.3p7+hemp2+fic/contrib/tkserv/tkserv.c	Thu Aug 26 23:31:55 2004
@@ -26,6 +26,7 @@
 ** 
 ** INET6 and fprintf() bug fixes by mro - 20000828
 ** some buffer overflows fixes and general cleanup by Beeth -- 20010307
+** IRCDCONF_DELIMITER instead of INET6 checking by fiction -- 20011028
 ** 
 */
 
@@ -52,6 +53,7 @@
 
 static char *nuh;
 int fd = -1, tklined = 0;
+char delimiter[2] = { IRCDCONF_DELIMITER, '\0' };
 
 /*
 ** Returns the current time in a formated way.
@@ -188,7 +190,7 @@ void process_server_output(char *line)
     {
         chmod(TKSERV_ACCESSFILE, S_IRUSR | S_IWRITE);
         chmod(TKSERV_LOGFILE, S_IRUSR | S_IWRITE);
-        exec_cmd("cp "CPATH" "TKSERV_IRCD_CONFIG_BAK);
+        exec_cmd("cp "TKLINE_PATH" "TKLINE_PATH_BAK);
         tks_log("Registration successful.");
     }
         
@@ -212,8 +214,8 @@ void process_server_output(char *line)
 /* reformats the server output */
 void parse_server_output(char *buffer)
 {
-    char *ch, buf[TKS_MAXBUFFER];
-    static char tmp[TKS_MAXBUFFER];
+    char *ch, buf[TKS_MAXBUFFER+1];
+    static char tmp[TKS_MAXBUFFER+1];
 
     /* server sent an empty line, so just return */
     if (!buffer && !*buffer)
@@ -250,6 +252,11 @@ int server_output(int fd, char *buffer)
 {
     int n;
     
+    /* We need to read one less than the size of the buffer.
+    ** The buffers are TKS_MAXBUFFER+1, if they were just
+    ** TKS_MAXBUFFER, if you read exactly that amount, buffer[n]
+    ** will overflow. -Hwy
+    */
     n = read(fd, buffer, TKS_MAXBUFFER);
     if (n>0)
     {
@@ -267,7 +274,11 @@ int server_output(int fd, char *buffer)
 int is_opered(void)
 {
     char *nick, *ch, *token, *u_num, *userh;
-    char buffer[TKS_MAXBUFFER];
+    /* read() will read in TKS_MAXBUFFER characters, plus a \0, creating
+    ** a nasty buffer overflow.  You'd never see it in tkserv...but it
+    ** does exist. -Hwy
+    */
+    char buffer[TKS_MAXBUFFER+1];
     int retv = 0;
 
     nick = (char *) strdup(nuh);
@@ -351,7 +362,7 @@ int must_be_opered()
     /* if the access file exists, check for auth */
     if ((fp = fopen(TKSERV_ACCESSFILE, "r")) != NULL)
     {
-        char buffer[TKS_MAXBUFFER];
+        char buffer[TKS_MAXBUFFER+1];
         char *access_uh, *token, *uh;
 
         while (fgets(buffer, TKS_MAXBUFFER, fp))
@@ -399,7 +410,7 @@ int is_authorized(char *pwd, char *host)
     char salt[3];
 #endif
     FILE *fp;
-    char buffer[TKS_MAXBUFFER];
+    char buffer[TKS_MAXBUFFER+1];
     char *access_uh, *access_pwd;
     char *token, *uh, *ch, *tlds = NULL;
     int retv = 0; /* 0 not authorized (perhaps *yet*); negative: errors */
@@ -562,31 +573,25 @@ int add_tkline(char *host, char *user, c
 {
     FILE *iconf;
 
-    if (iconf = fopen(CPATH, "a"))
+    if (iconf = fopen(TKLINE_PATH, "a"))
     {
         time_t now;
 
         now = time(NULL);
 
-#ifdef INET6
-        fprintf(iconf, "K%%%s%%%s%%%s%%0 # %d %u tkserv\n", host, reason, user, lifetime, now);
-#else
-        fprintf(iconf, "K:%s:%s:%s:0 # %d %u tkserv\n", host, reason, user, lifetime, now);
-#endif
+	fprintf(iconf, "K%c%s%c%s%c%s%c0 # %d %u tkserv\n", IRCDCONF_DELIMITER, host, IRCDCONF_DELIMITER, reason, 
+                IRCDCONF_DELIMITER, user, IRCDCONF_DELIMITER, lifetime, now);
         fclose(iconf);
         rehash(1);
-#ifdef INET6
-        tks_log("K%%%s%%%s%%%s%%0 added for %d hour(s) by %s.",
-#else
-        tks_log("K:%s:%s:%s:0 added for %d hour(s) by %s.",
-#endif
-            host, reason, user, lifetime, nuh);
+
+	tks_log("K%c%s%c%s%c%s%c0 added for %d hour(s) by %s.",
+            IRCDCONF_DELIMITER, host, IRCDCONF_DELIMITER, reason, IRCDCONF_DELIMITER, user, IRCDCONF_DELIMITER, lifetime, nuh);
 
         return(1);
     }
     else
     {
-        tks_log("Couldn't write to "CPATH);
+	 tks_log("Couldn't write to "TKLINE_PATH);
     }
 
     return(0);
@@ -597,15 +602,15 @@ int check_tklines(char *host, char *user
 {
     FILE *iconf, *iconf_tmp;
     
-    if ((iconf = fopen(CPATH, "r")) && (iconf_tmp = fopen(TKSERV_IRCD_CONFIG_TMP, "w")))
+    if ((iconf = fopen(TKLINE_PATH, "r")) && (iconf_tmp = fopen(TKLINE_PATH_TMP, "w")))
     {
         int count = 0, found = 0;
         time_t now;
-        char buffer[TKS_MAXBUFFER];
-        char buf_tmp[TKS_MAXBUFFER];
+        char buffer[TKS_MAXBUFFER+1];
+        char buf_tmp[TKS_MAXBUFFER+1];
         
         /* just in case... */
-        chmod(TKSERV_IRCD_CONFIG_TMP, S_IRUSR | S_IWRITE);
+        chmod(TKLINE_PATH_TMP, S_IRUSR | S_IWRITE);
 
         now = time(NULL);
 
@@ -628,27 +633,17 @@ int check_tklines(char *host, char *user
                 if (lifetime == -1)
                 {
                     char *token;
-                    char buf[TKS_MAXBUFFER];
+                    char buf[TKS_MAXBUFFER+1];
 
                     strcpy(buf, buffer);
 
-#ifdef INET6
-                    token = (char *) strtok(buf, "%");
-                    token = (char *) strtok(NULL, "%");
-#else
-                    token = (char *) strtok(buf, ":");
-                    token = (char *) strtok(NULL, ":");
-#endif
+                    token = (char *) strtok(buf, delimiter);
+                    token = (char *) strtok(NULL, delimiter); 
                     
                     if (!strcasecmp(token, host))
                     {
-#ifdef INET6
-                        token = (char *) strtok(NULL, "%");
-                        token = (char *) strtok(NULL, "%");
-#else
-                        token = (char *) strtok(NULL, ":");
-                        token = (char *) strtok(NULL, ":");
-#endif
+                        token = (char *) strtok(NULL, delimiter);
+                        token = (char *) strtok(NULL, delimiter);
                         
                         if (!strcasecmp(token, user))
                         {
@@ -668,7 +663,7 @@ int check_tklines(char *host, char *user
                 else
                 {
                     char *ch, *token;
-                    char buf[TKS_MAXBUFFER];
+                    char buf[TKS_MAXBUFFER+1];
                     unsigned long int lifetime, then;
                 
                     strcpy(buf, buffer);
@@ -694,8 +689,8 @@ int check_tklines(char *host, char *user
         
         fclose(iconf);
         fclose(iconf_tmp);
-        exec_cmd("cp %s %s", TKSERV_IRCD_CONFIG_TMP,CPATH);
-        unlink(TKSERV_IRCD_CONFIG_TMP);
+        exec_cmd("cp %s %s", TKLINE_PATH_TMP,TKLINE_PATH);
+        unlink(TKLINE_PATH_TMP);
         
         if (found)
         {
@@ -737,7 +732,7 @@ void service_pong(void)
 */
 void service_notice(char **args)
 {
-    if ((!strcmp(args[4], "reloading") && (!strcmp(args[5], TKSERV_IRCD_CONF))) ||
+    if ((!strcmp(args[4], "reloading") && (!strcmp(args[5], "ircd.conf"))) ||
         (!strcmp(args[3], "rehashing") && (!strcmp(args[4], "Server"))))
     {
         if (tklined)
@@ -765,7 +760,9 @@ void service_squery(char **args)
     {
         sendto_user(TKSERV_ADMIN_NAME);
         sendto_user(TKSERV_ADMIN_CONTACT);
+#ifdef TKSERV_ADMIN_OTHER
         sendto_user(TKSERV_ADMIN_OTHER);
+#endif
     }
     else if (!strcasecmp(cmd, "help"))
     {
@@ -875,17 +872,9 @@ void squery_tkline(char **args)
 
     while (args[i] && *args[i])
     {
-#ifdef INET6
-        if (strchr(args[i], '%'))
-#else
-        if (strchr(args[i], ':'))
-#endif
+        if (strchr(args[i], IRCDCONF_DELIMITER))
         {
-#ifdef INET6
-            sendto_user("Percent signs are only allowed in the password.");
-#else
-            sendto_user("Colons are only allowed in the password.");
-#endif
+            sendto_user("'%c' characters are only allowed in the password.", IRCDCONF_DELIMITER);
             return;
         }
 
@@ -1022,7 +1011,7 @@ void squery_tkline(char **args)
     }
     else if (!add_tkline(host, user, reason, lifetime))
     {
-        sendto_user("Error while trying to edit the "CPATH" file.");
+        sendto_user("Error while trying to edit the "TKLINE_PATH" file.");
     }
 }
 
@@ -1059,7 +1048,12 @@ void squery_quit(char **args)
 int main(int argc, char *argv[])
 {
 
-    char *host, *port, buffer[TKS_MAXBUFFER], last_buf[TKS_MAXBUFFER]; 
+    char *host, *port; 
+    /* read() will read in TKS_MAXBUFFER characters, plus a \0, creating
+    ** a nasty buffer overflow.  You'd never see it in tkserv...but it
+    ** does exist. -Hwy
+    */
+    char buffer[TKS_MAXBUFFER+1], last_buf[TKS_MAXBUFFER+1];
     char tmp[TKS_MAXPATH];
 
     int is_unix    = (argv[1] && *argv[1] == '/');
diff -urNp irc2.10.3p7+hemp2/ircd/channel.c irc2.10.3p7+hemp2+fic/ircd/channel.c
--- irc2.10.3p7+hemp2/ircd/channel.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/channel.c	Thu Sep  2 20:10:08 2004
@@ -47,7 +47,7 @@ static	void	add_invite __P((aClient *, a
 static	int	can_join __P((aClient *, aChannel *, char *));
 void	channel_modes __P((aClient *, char *, char *, aChannel *));
 static	int	check_channelmask __P((aClient *, aClient *, char *));
-static	aChannel *get_channel __P((aClient *, char *, int));
+static aChannel *create_channel __P((aClient *, char *));
 static	int	set_mode __P((aClient *, aClient *, aChannel *, int *, int,\
 				char **, char *,char *));
 static	void	free_channel __P((aChannel *));
@@ -544,6 +544,15 @@ aChannel *chptr;
 	return 0;
 }
 
+aChannel *find_channel_check(cptr, chname)
+Reg    aClient *cptr;
+Reg    char *chname;
+{
+       int len = strlen(chname);
+       if (MyClient(cptr) && len > CHANNELLEN) { chname[CHANNELLEN]='\0'; }
+       return find_channel(chname, NullChn);
+}
+
 aChannel *find_channel(chname, chptr)
 Reg	char	*chname;
 Reg	aChannel *chptr;
@@ -564,56 +573,56 @@ aClient	*mp;
 	smode = MODE_MODERATED|MODE_TOPICLIMIT|MODE_NOPRIVMSGS|MODE_ANONYMOUS|
 		MODE_QUIET;
 
-	chptr = get_channel(mp, "&ERRORS", CREATE);
+	chptr = create_channel(mp, "&ERRORS");
 	strcpy(chptr->topic, "SERVER MESSAGES: server errors");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&NOTICES", CREATE);
+	chptr = create_channel(mp, "&NOTICES");
 	strcpy(chptr->topic, "SERVER MESSAGES: warnings and notices");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&KILLS", CREATE);
+	chptr = create_channel(mp, "&KILLS");
 	strcpy(chptr->topic, "SERVER MESSAGES: operator and server kills");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&CHANNEL", CREATE);
+	chptr = create_channel(mp, "&CHANNEL");
 	strcpy(chptr->topic, "SERVER MESSAGES: fake modes");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&NUMERICS", CREATE);
+	chptr = create_channel(mp, "&NUMERICS");
 	strcpy(chptr->topic, "SERVER MESSAGES: numerics received");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&SERVERS", CREATE);
+	chptr = create_channel(mp, "&SERVERS");
 	strcpy(chptr->topic, "SERVER MESSAGES: servers joining and leaving");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&HASH", CREATE);
+	chptr = create_channel(mp, "&HASH");
 	strcpy(chptr->topic, "SERVER MESSAGES: hash tables growth");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&LOCAL", CREATE);
+	chptr = create_channel(mp, "&LOCAL");
 	strcpy(chptr->topic, "SERVER MESSAGES: notices about local connections");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
-	chptr = get_channel(mp, "&SERVICES", CREATE);
+	chptr = create_channel(mp, "&SERVICES");
 	strcpy(chptr->topic, "SERVER MESSAGES: services joining and leaving");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
 #if defined(USE_IAUTH)
-	chptr = get_channel(mp, "&AUTH", CREATE);
+	chptr = create_channel(mp, "&AUTH");
 	strcpy(chptr->topic,
 	       "SERVER MESSAGES: messages from the authentication slave");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode;
 #endif
-	chptr = get_channel(mp, "&DEBUG", CREATE);
+	chptr = create_channel(mp, "&DEBUG");
 	strcpy(chptr->topic, "SERVER MESSAGES: debug messages [you shouldn't be here! ;)]");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode|MODE_SECRET;
 
 #ifdef  CLIENTS_CHANNEL
-	chptr = get_channel(mp, "&CLIENTS", CREATE);
+	chptr = create_channel(mp, "&CLIENTS");
 	strcpy(chptr->topic,"SERVER MESSAGES: client activities [various]");
 	add_user_to_channel(chptr, mp, CHFL_CHANOP);
 	chptr->mode.mode = smode|MODE_SECRET;
@@ -893,7 +902,7 @@ char	*parv[];
 	     name = strtoken(&p, NULL, ","))
 	    {
 		clean_channelname(name);
-		chptr = find_channel(name, NullChn);
+                chptr = find_channel_check(sptr, name);
 		if (chptr == NullChn)
 		    {
 			parv[1] = name;
@@ -1910,44 +1919,49 @@ char	*chname;
 }
 
 /*
-**  Get Channel block for i (and allocate a new channel
-**  block, if it didn't exists before).
-*/
-static	aChannel *get_channel(cptr, chname, flag)
-aClient *cptr;
-char	*chname;
-int	flag;
-    {
+ * Allocate channel block
+ */
+
+static aChannel *create_channel(cptr, chname)
+  aClient *cptr;
+  char   *chname;
+{
 	Reg	aChannel *chptr;
-	int	len;
+        int     len = strlen(chname);
 
-	if (BadPtr(chname))
-		return NULL;
+        chptr = (aChannel *)MyMalloc(sizeof(aChannel) + len);
+        bzero((char *)chptr, sizeof(aChannel));
+        strncpyzt(chptr->chname, chname, len+1);
+        if (channel)
+                channel->prevch = chptr;
+        chptr->prevch = NULL;
+        chptr->nextch = channel;
+        chptr->history = 0;
+        channel = chptr;
+        (void)add_to_channel_hash_table(chname, chptr);
+        return chptr;
+}
 
-	len = strlen(chname);
-	if (MyClient(cptr) && len > CHANNELLEN)
-	    {
-		len = CHANNELLEN;
-		*(chname+CHANNELLEN) = '\0';
-	    }
-	if ((chptr = find_channel(chname, (aChannel *)NULL)))
-		return (chptr);
-	if (flag == CREATE)
-	    {
-		chptr = (aChannel *)MyMalloc(sizeof(aChannel) + len);
-		bzero((char *)chptr, sizeof(aChannel));
-		strncpyzt(chptr->chname, chname, len+1);
-		if (channel)
-			channel->prevch = chptr;
-		chptr->prevch = NULL;
-		chptr->nextch = channel;
-		chptr->history = 0;
-		channel = chptr;
-		(void)add_to_channel_hash_table(chname, chptr);
-	    }
-	return chptr;
-    }
+#ifdef IGNORE_STRANGERS
+/*
+ * Return first common channel users aptr and bptr are on.
+ * NullChn if none.
+ */
+aChannel *CommonChannel(anUser *aptr, anUser *bptr) {
+    Link *lp, *lp2;
 
+    if (!aptr || !bptr) { return NullChn; }
+    for (lp = aptr->channel; lp; lp=lp->next) {
+        for (lp2 = bptr->channel; lp2; lp2=lp2->next) {
+            if ((lp->value.chptr == lp2->value.chptr) &&
+                (!IsAnonymous(lp->value.chptr))){
+                    return lp->value.chptr;
+            }
+        }
+    }
+    return NullChn;
+}
+#endif
 
 static	void	add_invite(sptr, cptr, chptr)
 aClient *sptr;
@@ -2297,8 +2311,21 @@ char	*parv[];
 				sendto_channel_butserv(chptr, sptr,
 						PartFmt,
 						parv[0], chptr->chname,
-						IsAnonymous(chptr) ? "None" :
-						(key ? key : parv[0]));
+                                               (IsAnonymous(chptr)
+#ifdef NOCOMMENTABUSE
+					       || can_send(sptr, chptr))
+#else
+       						)
+#endif
+#ifdef EMPTYCOMMENTS
+					       ? "" :
+#else
+					       ? "None" :
+                                               (key ? key : parv[0]));
+#endif
+#ifdef EMPTYCOMMENTS
+                                               (key ? key : ""));
+#endif
 				remove_user_from_channel(sptr, chptr);
 			    }
 			sendto_match_servs(NULL, cptr, ":%s JOIN 0 :%s",
@@ -2311,7 +2338,7 @@ char	*parv[];
 		else
 			clean_channelname(name), s = NULL;
 
-		chptr = get_channel(sptr, name, !CREATE);
+		chptr = find_channel_check(sptr, name);
 
 		if (chptr && IsMember(sptr, chptr))
 			continue;
@@ -2319,7 +2346,7 @@ char	*parv[];
 		if (MyConnect(sptr) && !(chptr && IsQuiet(chptr)) &&
 		    sptr->user->joined >= MAXCHANNELSPERUSER) {
 			sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS,
-				   parv[0]), name);
+				   parv[0]), name, MAXCHANNELSPERUSER);
 			/* can't return, need to send the info everywhere */
 			continue;
 		}
@@ -2332,8 +2359,9 @@ char	*parv[];
 			return exit_client(sptr, sptr, &me, "Virus Carrier");
 		    }
 
-		if (!chptr)
-			chptr = get_channel(sptr, name, CREATE);
+		if (!chptr) {
+			chptr = create_channel(sptr, name);
+                }
 
 		if (!chptr)
 		{
@@ -2442,7 +2470,7 @@ char	*parv[];
 				if (chptr->topic_time>0)
 				{
 					sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME, parv[0]),
-						name, IsAnonymous(chptr) ? "Anonymous!Anonymous@Anomyous" : chptr->topic_nuh,
+						name, IsAnonymous(chptr) ? "anonymous!anonymous@anonymous." : chptr->topic_nuh,
 						chptr->topic_time);
 				}
 #endif
@@ -2574,7 +2602,10 @@ char	*parv[];
 					    get_client_name(cptr, TRUE));
 				return 0;
 			    }
-			chptr = get_channel(acptr, parv[1], CREATE);
+
+			chptr = find_channel_check(acptr, parv[1]);
+			if (!chptr) { chptr = create_channel(acptr, parv[1]); }
+
 			if (!IsChannelName(parv[1]) || chptr == NULL)
 			    {
 				sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL,
@@ -2687,6 +2718,9 @@ char	*parv[];
 	Reg	aChannel *chptr;
 	char	*p = NULL, *name, *comment = "";
 	int	size;
+#ifdef NOCOMMENTABUSE
+	char *comment2 = "";
+#endif
 
 	if (parc < 2 || parv[1][0] == '\0')
 	    {
@@ -2697,10 +2731,16 @@ char	*parv[];
 	*buf = '\0';
 
 	parv[1] = canonize(parv[1]);
+
 	comment = (BadPtr(parv[2])) ? "" : parv[2];
+
 	if (strlen(comment) > TOPICLEN)
 		comment[TOPICLEN] = '\0';
 
+#ifndef NOCOMMENTABUSE
+	comment2 = comment;
+#endif
+
 	/*
 	** Broadcasted to other servers is ":nick PART #chan,#chans :comment",
 	** so we must make sure buf does not contain too many channels or later
@@ -2712,7 +2752,7 @@ char	*parv[];
 
 	for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
 	    {
-		chptr = get_channel(sptr, name, 0);
+		chptr = find_channel_check(sptr, name);
 		if (!chptr)
 		    {
 			if (MyPerson(sptr))
@@ -2730,6 +2770,9 @@ char	*parv[];
 			continue;
 		    }
 
+#ifdef NOCOMMENTABUSE
+		    comment2 = (can_send(sptr, chptr)) ? "" : comment;
+#endif
 		/*
 		**  Remove user from the old channel (if any)
 		*/
@@ -2746,7 +2789,7 @@ char	*parv[];
 					/* Anyway, if it would not fit in the
 					** buffer, send it right away. --B */
 					sendto_serv_butone(cptr, PartFmt,
-						parv[0], buf, comment);
+						parv[0], buf, comment2);
 					*buf = '\0';
 				}
 				if (*buf)
@@ -2756,13 +2799,13 @@ char	*parv[];
 		    }
 		else
 			sendto_match_servs(chptr, cptr, PartFmt,
-				   	   parv[0], name, comment);
+				   	   parv[0], name, comment2);
 		sendto_channel_butserv(chptr, sptr, PartFmt,
-				       parv[0], name, comment);
+				       parv[0], name, comment2);
 		remove_user_from_channel(sptr, chptr);
 	    }
 	if (*buf)
-		sendto_serv_butone(cptr, PartFmt, parv[0], buf, comment);
+		sendto_serv_butone(cptr, PartFmt, parv[0], buf, comment2);
 	return 4;
     }
 
@@ -2793,7 +2836,11 @@ char	*parv[];
 	if (IsServer(sptr))
 		sendto_flag(SCH_NOTICE, "KICK from %s for %s %s",
 			    parv[0], parv[1], parv[2]);
+#ifdef EMPTYCOMMENTS
+	comment = (BadPtr(parv[3])) ? "" : parv[3];
+#else
 	comment = (BadPtr(parv[3])) ? parv[0] : parv[3];
+#endif
 	if (strlen(comment) > (size_t) TOPICLEN)
 		comment[TOPICLEN] = '\0';
 
@@ -2805,7 +2852,7 @@ char	*parv[];
 		*nickbuf = '\0';
 		if (penalty >= MAXPENALTY && MyPerson(sptr))
 			break;
-		chptr = get_channel(sptr, name, !CREATE);
+		chptr = find_channel_check(sptr, name);
 		if (!chptr)
 		    {
 			if (MyPerson(sptr))
@@ -2941,7 +2988,7 @@ char	*parv[];
 
 		if (!chptr)
 		    {
-			sendto_one(sptr, rpl_str(RPL_NOTOPIC, parv[0]), name);
+			sendto_one(sptr, err_str(ERR_NOTONCHANNEL, parv[0]), name);
 			return penalty;
 		    }
 
@@ -2958,7 +3005,7 @@ char	*parv[];
 					   chptr->chname, chptr->topic);
 #ifdef TOPICWHOTIME
 				sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME, parv[0]),
-					chptr->chname, IsAnonymous(chptr) ? "Anonymous!anonymous@anonymous" : chptr->topic_nuh,
+					chptr->chname, IsAnonymous(chptr) ? "anonymous!anonymous@anonymous." : chptr->topic_nuh,
 					chptr->topic_time);
 #endif
 			}
@@ -3040,7 +3087,7 @@ char	*parv[];
 			if (acptr->user->flags & FLAGS_AWAY)
 				sendto_one(sptr, rpl_str(RPL_AWAY, parv[0]),
 					   acptr->name, (acptr->user->away) ? 
-					   acptr->user->away : "Gone");
+					   acptr->user->away : DEFAWAY);
 		    }
 		return 3;
 	    }
@@ -3073,7 +3120,7 @@ char	*parv[];
 			sendto_one(sptr, rpl_str(RPL_AWAY, parv[0]),
 				   acptr->name,
 				   (acptr->user->away) ? acptr->user->away :
-				   "Gone");
+				   DEFAWAY);
 	    }
 
 	if (MyConnect(acptr))
diff -urNp irc2.10.3p7+hemp2/ircd/channel_def.h irc2.10.3p7+hemp2+fic/ircd/channel_def.h
--- irc2.10.3p7+hemp2/ircd/channel_def.h	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/channel_def.h	Thu Aug 26 23:31:55 2004
@@ -17,9 +17,6 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define CREATE 1	/* whether a channel should be
-			   created or just tested for existance */
-
 #define	MODEBUFLEN	200
 
 #define NullChn	((aChannel *)0)
diff -urNp irc2.10.3p7+hemp2/ircd/channel_ext.h irc2.10.3p7+hemp2+fic/ircd/channel_ext.h
--- irc2.10.3p7+hemp2/ircd/channel_ext.h	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/channel_ext.h	Thu Aug 26 23:31:55 2004
@@ -34,6 +34,7 @@ extern aChannel *channel;
 #else /* CHANNEL_C */
 #define EXTERN
 #endif /* CHANNEL_C */
+EXTERN aChannel *CommonChannel __P((anUser *aptr, anUser *bptr));
 EXTERN void remove_user_from_channel __P((aClient *sptr, aChannel *chptr));
 EXTERN int is_chan_op __P((aClient *cptr, aChannel *chptr));
 EXTERN int has_voice __P((aClient *cptr, aChannel *chptr));
diff -urNp irc2.10.3p7+hemp2/ircd/chkconf.c irc2.10.3p7+hemp2+fic/ircd/chkconf.c
--- irc2.10.3p7+hemp2/ircd/chkconf.c	Mon May 14 07:46:46 2001
+++ irc2.10.3p7+hemp2+fic/ircd/chkconf.c	Thu Aug 26 23:31:55 2004
@@ -320,6 +320,13 @@ int	opt;
 			case 'y':
 			        aconf->status = CONF_CLASS;
 		        	break;
+#ifdef W_LINE
+			case 'W':
+			case 'w':
+				aconf->status = CONF_WEB;
+				break;
+#endif
+
 		    default:
 			(void)fprintf(stderr,
 				"\tERROR: unknown conf line letter (%c)\n",
@@ -461,7 +468,11 @@ int	opt;
 			aconf->passwd = nullfield;
 		if (!aconf->host)
 			aconf->host = nullfield;
+#ifdef W_LINE
+		if (aconf->status & (CONF_ME|CONF_ADMIN|CONF_WEB))
+#else
 		if (aconf->status & (CONF_ME|CONF_ADMIN))
+#endif
 		    {
 			if (flags & aconf->status)
 				(void)fprintf(stderr,
@@ -761,8 +772,13 @@ aConfItem *top;
 static	char	confchar(status)
 u_int	status;
 {
-	static	char	letrs[] = "QIiCcNoOMKARYSLPHV";
-	char	*s = letrs;
+#ifdef W_LINE
+	static  char    letters[] = "QIiCcNoOMKARYSLPHVBkDW";
+#else
+	static  char    letters[] = "QIiCcNoOMKARYSLPHVBkD";
+#endif
+
+	char	*s = letters;
 
 	status &= ~(CONF_MATCH|CONF_ILLEGAL);
 
diff -urNp irc2.10.3p7+hemp2/ircd/ircd.c irc2.10.3p7+hemp2+fic/ircd/ircd.c
--- irc2.10.3p7+hemp2/ircd/ircd.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/ircd.c	Thu Aug 26 23:31:55 2004
@@ -1071,7 +1071,7 @@ char	*argv[];
 		if (acptr == NULL && !(bootopt & BOOT_INETD))
 			exit(-1);
 		/* Is there an M-line? */
-		if (!find_me())
+		if (!find_conf_one(CONF_ME))
 			exit(-1);
 	    }
 	initialconf = 0;
diff -urNp irc2.10.3p7+hemp2/ircd/s_bsd.c irc2.10.3p7+hemp2+fic/ircd/s_bsd.c
--- irc2.10.3p7+hemp2/ircd/s_bsd.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/s_bsd.c	Thu Aug 26 23:31:55 2004
@@ -2949,7 +2949,7 @@ int	len;
 	bzero((char *)&mysk, sizeof(mysk));
 	mysk.SIN_FAMILY = AFINET;
 	
-	if ((aconf = find_me())->passwd && isdigit(*aconf->passwd))
+	if ((aconf = find_conf_one(CONF_ME))->passwd && isdigit(*aconf->passwd))
 #ifdef INET6
 		if(!inetpton(AF_INET6, aconf->passwd, mysk.sin6_addr.s6_addr))
 			bcopy(minus_one, mysk.sin6_addr.s6_addr, IN6ADDRSZ);
diff -urNp irc2.10.3p7+hemp2/ircd/s_conf.c irc2.10.3p7+hemp2+fic/ircd/s_conf.c
--- irc2.10.3p7+hemp2/ircd/s_conf.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/s_conf.c	Thu Aug 26 23:31:55 2004
@@ -184,12 +184,51 @@ char	*sockhost;
 			continue;
 		if (aconf->port && aconf->port != cptr->acpt->port)
 			continue;
-		if (!aconf->host || !aconf->name)
-			goto attach_iline;
+                if (!aconf->host || !aconf->name)
+                        continue;       /* Try another I:line. */
+
+        /* Try to match the IP first */
+
+		if (index(aconf->host, '@')) {
+			strncpyzt(uhost, cptr->username, sizeof(uhost));
+			(void)strcat(uhost, "@");
+		} else {
+			*uhost = '\0';
+        }
+		(void)strncat(uhost, sockhost, sizeof(uhost) - strlen(uhost));
+        if (aconf->host[0] == '\0') {
+            /* There is no IP in conf, no need to bother */
+            goto hostname_try;
+        }
+		if (strchr(aconf->host, '/')) {		/* 1.2.3.0/24 */
+			if (match_ipmask(aconf->host, cptr)) {
+              /* not an IP match */
+#ifdef AND_ILINE_BEHAVIOR
+              continue;
+#else
+              goto hostname_try;
+#endif
+            }
+        } else if (match(aconf->host, uhost)) {	/* 1.2.3.* */
+#ifdef AND_ILINE_BEHAVIOR
+              continue; 
+#else
+              goto hostname_try;
+#endif
+        }
+
+
+        /* And now the hostname too */
+hostname_try:
+
+		if (*aconf->name == '\0' && hp) {
+			strncpyzt(uhost, hp->h_name, sizeof(uhost));
+			add_local_domain(uhost, sizeof(uhost) - strlen(uhost));
+		}
+
 		if (hp)
 			for (i = 0, hname = hp->h_name; hname;
-			     hname = hp->h_aliases[i++])
-			    {
+			     hname = hp->h_aliases[i++]) { 
 				strncpyzt(fullname, hname,
 					sizeof(fullname));
 				add_local_domain(fullname,
@@ -205,29 +244,18 @@ char	*sockhost;
 					*uhost = '\0';
 				(void)strncat(uhost, fullname,
 					sizeof(uhost) - strlen(uhost));
-				if (!match(aconf->name, uhost))
-					goto attach_iline;
-			    }
+				if (!match(aconf->name, uhost)) {
+                    /* A match */
+                    goto attach_iline;
+				}
+			 }
+#ifdef ILINE_FLAGS
+        if (aconf->name[0] != '\0') {
+            /* There is a hostname in conf */
+            continue;
+        }
+#endif
 
-		if (index(aconf->host, '@'))
-		    {
-			strncpyzt(uhost, cptr->username, sizeof(uhost));
-			(void)strcat(uhost, "@");
-		    }
-		else
-			*uhost = '\0';
-		(void)strncat(uhost, sockhost, sizeof(uhost) - strlen(uhost));
-		if (strchr(aconf->host, '/'))		/* 1.2.3.0/24 */
-		    {
-			if (match_ipmask(aconf->host, cptr))
-				continue;
-                } else if (match(aconf->host, uhost))	/* 1.2.3.* */
-			continue;
-		if (*aconf->name == '\0' && hp)
-		    {
-			strncpyzt(uhost, hp->h_name, sizeof(uhost));
-			add_local_domain(uhost, sizeof(uhost) - strlen(uhost));
-		    }
 attach_iline:
 		if (aconf->status & CONF_RCLIENT)
 			SetRestricted(cptr);
@@ -475,23 +503,12 @@ aClient *cptr;
 	return 0;
 }
 
-
-aConfItem *find_admin()
-    {
-	Reg	aConfItem	*aconf;
-
-	for (aconf = conf; aconf; aconf = aconf->next)
-		if (aconf->status & CONF_ADMIN)
-			break;
-	
-	return (aconf);
-    }
-
-aConfItem *find_me()
+aConfItem *find_conf_one(status)
+Reg u_int status;
     {
 	Reg	aConfItem	*aconf;
 	for (aconf = conf; aconf; aconf = aconf->next)
-		if (aconf->status & CONF_ME)
+		if (aconf->status & status)
 			break;
 	
 	return (aconf);
@@ -1205,6 +1222,12 @@ int	opt;
 			case 'y':
 			        aconf->status = CONF_CLASS;
 		        	break;
+#ifdef W_LINE
+			case 'W':
+			case 'w':
+				aconf->status = CONF_WEB;
+				break;
+#endif
 		    default:
 			Debug((DEBUG_ERROR, "Error in config file: %s", line));
 			break;
diff -urNp irc2.10.3p7+hemp2/ircd/s_conf_ext.h irc2.10.3p7+hemp2+fic/ircd/s_conf_ext.h
--- irc2.10.3p7+hemp2/ircd/s_conf_ext.h	Fri Feb  9 12:35:34 2001
+++ irc2.10.3p7+hemp2+fic/ircd/s_conf_ext.h	Thu Aug 26 23:31:55 2004
@@ -40,8 +40,7 @@ EXTERN int attach_Iline __P((aClient *cp
 EXTERN aConfItem *count_cnlines __P((Reg Link *lp));
 EXTERN int detach_conf __P((aClient *cptr, aConfItem *aconf));
 EXTERN int attach_conf __P((aClient *cptr, aConfItem *aconf));
-EXTERN aConfItem *find_admin();
-EXTERN aConfItem *find_me();
+EXTERN aConfItem *find_conf_one __P((u_int status));
 EXTERN aConfItem *attach_confs __P((aClient *cptr, char *name, int statmask));
 EXTERN aConfItem *attach_confs_host __P((aClient *cptr, char *host,
 					 int statmask));
diff -urNp irc2.10.3p7+hemp2/ircd/s_debug.c irc2.10.3p7+hemp2+fic/ircd/s_debug.c
--- irc2.10.3p7+hemp2/ircd/s_debug.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/s_debug.c	Thu Sep  2 15:51:03 2004
@@ -266,6 +266,29 @@ char jvopts[] = {
 #endif
 '\0'
 };
+
+char ficopts[] = {
+#ifdef NOCOMMENTABUSE
+'N',
+#endif
+#ifdef IGNORE_STRANGERS
+'c',
+#endif
+#ifdef EMPTYCOMMENTS
+'E',
+#endif
+#ifdef STATS_L_OPERONLY
+'L',
+#endif
+#ifdef AND_ILINE_BEHAVIOR
+'A',
+#endif
+#ifdef W_LINE
+'W',
+#endif
+'\0'
+};
+
 #ifdef DEBUGMODE
 static	char	debugbuf[2*READBUF_SIZE]; /* needs to be big.. */
 
@@ -434,10 +457,16 @@ char	*nick;
 	return;
 }
 
+#define FICVERSION "2.9.2004"
+
 void	send_defines(cptr, nick)
 aClient *cptr;
 char	*nick;
 {
+#ifdef W_LINE
+	Reg     aConfItem *aconf = NULL;
+#endif
+
     	sendto_one(cptr, ":%s %d %s :HUB:%s MS:%d", 
 		   ME, RPL_STATSDEFINE, nick,
 #ifdef HUB
@@ -494,7 +523,16 @@ char	*nick;
 	-1,-1,-1
 #endif
 		);
+#ifdef W_LINE
+if ((aconf = (aConfItem*)find_conf_one(CONF_WEB)) && !BadPtr(aconf->host)) {
+	sendto_one(cptr, ":%s %d %s :fiction:%s (%.200s) version: %s",
+		ME, RPL_STATSDEFINE, nick, ficopts, aconf->host, FICVERSION);
+} else
+#endif
+	sendto_one(cptr, ":%s %d %s :fiction:%s version: %s",
+		ME, RPL_STATSDEFINE, nick, ficopts, FICVERSION);
 }
+#undef FICVERSION
 
 void	count_memory(cptr, nick, debug)
 aClient	*cptr;
@@ -587,7 +625,7 @@ int	debug;
 			if (acptr->user)
 			    {
 				d_us++;
-				for (link = acptr->user->invited; link;
+				for (link = (Link*)acptr->user->invited; link;
 				     link = link->next)
 					d_usi++;
 				d_usc += acptr->user->joined;
diff -urNp irc2.10.3p7+hemp2/ircd/s_err.c irc2.10.3p7+hemp2+fic/ircd/s_err.c
--- irc2.10.3p7+hemp2/ircd/s_err.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/s_err.c	Thu Sep  2 20:03:27 2004
@@ -40,7 +40,11 @@ static	Numeric	local_replies[] = {
 /* 001 */	{ RPL_WELCOME, ":Welcome to the Internet Relay Network %s" },
 /* 002 */	{ RPL_YOURHOST, ":Your host is %s, running version %s" },
 /* 003 */	{ RPL_CREATED, ":This server was created %s" },
-/* 004 */	{ RPL_MYINFO, "%s %s aoOirw abeiIklmnoOpqrstv" },
+#ifdef IGNORE_STRANGERS
+/* 004 */       { RPL_MYINFO, "%s %s acoOirw abeiIklmnoOpqrstv" },
+#else
+/* 004 */       { RPL_MYINFO, "%s %s aoOirw abeiIklmnoOpqrstv" },
+#endif
 #ifdef SEND_ISUPPORT
 /* 005 */	//{ RPL_ISUPPORT, "MAP PREFIX=(ov)@+ MODES=3 CHANTYPES=#&!+ MAXCHANNELS=%d NICKLEN=%d TOPICLEN=%d KICKLEN=%d NETWORK=%s CHANMODES=beI,k,l,imnpstaqr :are supported by this server" },
 /* 005 */	{ RPL_ISUPPORT, "%s :are supported by this server" },
@@ -74,7 +78,7 @@ static	Numeric	numeric_errors[] = {
 /* 402 */	{ ERR_NOSUCHSERVER, "%s :No such server" },
 /* 403 */	{ ERR_NOSUCHCHANNEL, "%s :No such channel" },
 /* 404 */	{ ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel" },
-/* 405 */	{ ERR_TOOMANYCHANNELS, "%s :You have joined too many channels" },
+/* 405 */	{ ERR_TOOMANYCHANNELS, "%s :You have joined too many channels (limit is %d)" },
 /* 406 */	{ ERR_WASNOSUCHNICK, "%s :There was no such nickname" },
 /* 407 */	{ ERR_TOOMANYTARGETS,
 		"%s :%s recipients. %s" },
diff -urNp irc2.10.3p7+hemp2/ircd/s_misc.c irc2.10.3p7+hemp2+fic/ircd/s_misc.c
--- irc2.10.3p7+hemp2/ircd/s_misc.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/s_misc.c	Thu Aug 26 23:31:55 2004
@@ -363,6 +363,9 @@ char	*comment;	/* Reason for the exit */
 	Reg	aClient	*acptr;
 	Reg	aClient	*next;
 	Reg	aServer *asptr;
+#ifdef W_LINE
+	Reg     aConfItem *aconf = NULL;
+#endif
 	char	comment1[HOSTLEN + HOSTLEN + 2];
 	int	flags = 0;
 
@@ -418,29 +421,53 @@ char	*comment;	/* Reason for the exit */
 			else
 				istat.is_unknown--;
 #ifdef DELAY_CLOSE
-	                if (cptr && cptr->user && (cptr->user->flags
-						& FLAGS_BADBOY))
-               		{ 
-                           SPRINTF(cptr->buffer, "ERROR :Closing Link: %s (%s)",
-                           get_client_name(sptr,FALSE), comment);
-                        }
+			if (cptr && cptr->user && (cptr->user->flags
+                                               & FLAGS_BADBOY))
+			{
+#ifdef W_LINE
+			  if ((comment[0] != '"') && !IsClient(sptr) && (sptr->exitc != EXITC_PING) &&
+				(aconf = (aConfItem*)find_conf_one(CONF_WEB)) && !BadPtr(aconf->host)) {
+#if 0 
+
+					SPRINTF(cptr->buffer, ":%s NOTICE %s :%.200s\nERROR :Closing Link: %s (%s)", ME,
+					(sptr->name)?(sptr->name):("*"), aconf->host, get_client_name(sptr,FALSE), comment);
+#endif
+
+                    sendto_one(sptr, ":%s NOTICE %s :%.200s", ME, (sptr->name)?(sptr->name):("*"), aconf->host);
+                    SPRINTF(cptr->buffer, "ERROR :Closing Link: %s (%s)",
+                            get_client_name(sptr,FALSE), comment);
+			  } else {
+#endif
+			  		SPRINTF(cptr->buffer, "ERROR :Closing Link: %s (%s)",
+						get_client_name(sptr,FALSE), comment);
+#ifdef W_LINE
+			}
+#endif
+			}
                         else
 #endif
-		        {
-		        	if (cptr != NULL && sptr != cptr)
-				{
-					sendto_one(sptr, "ERROR :Closing Link: %s %s (%s)",
-				   	get_client_name(sptr,FALSE),
-				   	cptr->name, comment);
-				}
-		      		else
-				{
-					sendto_one(sptr, "ERROR :Closing Link: %s (%s)",
-				   	get_client_name(sptr,FALSE), comment);
-
-		    		}
+			{
+#ifdef W_LINE
+			if ((comment[0] != '"') && !IsClient(sptr) && (sptr->exitc != EXITC_PING)) {
+			  if ((aconf = (aConfItem*)find_conf_one(CONF_WEB)) && !BadPtr(aconf->host)) {
+			    sendto_one(sptr, ":%s NOTICE %s :%.200s", ME, (sptr->name)?(sptr->name):("*"), aconf->host);
+			  }
 			}
-		        if (sptr->auth != sptr->username)
+#endif
+                               if (cptr != NULL && sptr != cptr)
+                               {
+                                       sendto_one(sptr, "ERROR :Closing Link: %s %s (%s)",
+                                       get_client_name(sptr,FALSE),
+                                       cptr->name, comment);
+                               }
+                               else
+                               {
+                                       sendto_one(sptr, "ERROR :Closing Link: %s (%s)",
+                                       get_client_name(sptr,FALSE), comment);
+
+                               }
+                       }
+                       if (sptr->auth != sptr->username)
 			  {
 			    istat.is_authmem -= strlen(sptr->auth) + 1;
 			    istat.is_auth -= 1;
@@ -759,7 +786,41 @@ char	*comment;
 		if ((sptr->flags & FLAGS_KILLED) == 0)
 		    {
 			if ((sptr->flags & FLAGS_SPLIT) == 0)
-			    {
+		    {
+#ifdef NOCOMMENTABUSE
+               /*
+                ** For those channels where user can't speak
+                ** a part is generated and user removed.
+                ** If user is local also send to all
+                ** servers that he parted. --fiction
+                */
+                             if ((comment[0] == '"')) {
+                               /* No point to check if the user didn't generate the QUIT himself */
+                               if ((sptr->user) && (lp = sptr->user->channel)) {
+                                 while (lp) {
+                                   if (!IsQuiet(lp->value.chptr) && can_send(sptr, lp->value.chptr)) {
+#ifdef EMPTYCOMMENTS
+                                      sendto_channel_butserv(lp->value.chptr, sptr, ":%s PART %s :",
+#else
+                                     sendto_channel_butserv(lp->value.chptr, sptr, ":%s PART %s :None",
+#endif
+                                                               sptr->name, lp->value.chptr->chname);
+                                      if (sptr == cptr) { /* exiting user is local? */
+#ifdef EMPTYCOMMENTS
+                                        sendto_match_servs(lp->value.chptr, sptr, ":%s PART %s :",
+#else
+                                       sendto_channel_butserv(lp->value.chptr, sptr, ":%s PART %s :None",
+#endif
+                                                           sptr->name, lp->value.chptr->chname);
+
+                                      }
+                                     remove_user_from_channel(sptr, lp->value.chptr);
+                                      lp = sptr->user->channel;
+                                   } else { lp=lp->next; } /* if you remove one element next becomes current anyway */
+                                 }
+                               }
+                             }
+#endif
 				sendto_serv_butone(cptr, ":%s QUIT :%s",
 						   sptr->name, comment);
 #ifdef	USE_SERVICES
@@ -849,12 +910,16 @@ char	*comment;
 						lp->value.chptr->history = timeofday + DELAYCHASETIMELIMIT;
 				if (IsAnonymous(lp->value.chptr) &&
 				    !IsQuiet(lp->value.chptr))
+#ifdef EMPTYCOMMENTS
+					sendto_channel_butserv(lp->value.chptr, sptr, ":%s PART %s :", sptr->name, lp->value.chptr->chname);
+#else
 					sendto_channel_butserv(lp->value.chptr, sptr, ":%s PART %s :None", sptr->name, lp->value.chptr->chname);
+#endif
 				remove_user_from_channel(sptr,lp->value.chptr);
 			    }
 
 			/* Clean up invitefield */
-			while ((lp = sptr->user->invited))
+			while ((lp = (Link*)sptr->user->invited))
 				del_invite(sptr, lp->value.chptr);
 				/* again, this is all that is needed */
 
diff -urNp irc2.10.3p7+hemp2/ircd/s_serv.c irc2.10.3p7+hemp2+fic/ircd/s_serv.c
--- irc2.10.3p7+hemp2/ircd/s_serv.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/s_serv.c	Thu Aug 26 23:31:55 2004
@@ -1636,8 +1636,24 @@ char *to;
 		
 	}
 }
-	
+#else 
+static void report_listeners(aClient *sptr, char *to)
+{
+        aConfItem *tmp;
+
+        for (tmp = conf; tmp; tmp = tmp->next)
+        {
+                if ((tmp->status & CONF_LISTEN_PORT))
+                {
+                        sendto_one(sptr, ":%s %d %s :%s %d %d", ME,
+                                RPL_STATSDEFINE, to, BadPtr(tmp->host) ?
+                                "*" : tmp->host, tmp->port,
+                                tmp->clients);
+                }
+        }
+}
 #endif
+
 int	m_stats(cptr, sptr, parc, parv)
 aClient *cptr, *sptr;
 int	parc;
@@ -1732,6 +1748,13 @@ char	*parv[];
 		stat = 'f';
 #endif
 	case 'L' : case 'l' :
+#ifdef STATS_L_OPERONLY
+               if (!IsAnOper(sptr) && (stat=='L'))
+               {
+                       sendto_one(sptr, err_str(ERR_NOPRIVILEGES, parv[0]));
+                       return 2;
+               }
+#endif
 		/*
 		 * send info about connections which match, or all if the
 		 * mask matches ME.  Only restrictions are on those who
@@ -1831,8 +1854,15 @@ char	*parv[];
 		report_configured_links(cptr, parv[0], CONF_OPS);
 		break;
 	case 'P' : /* ports listening */
-		report_listeners(sptr, parv[0]);
-		break;
+#ifdef DELAY_ACCEPT
+                if (IsAnOper(sptr)) { 
+                  report_listeners(sptr,parv[0]);  /* report_listeners by jv */
+                  break;
+                } 
+#else
+		report_listeners(sptr, parv[0]); /* report_listeners by p6 - more harmless */
+                break;
+#endif
 	case 'p' : /* ircd ping stats */
 		report_ping(sptr, parv[0]);
 		break;
@@ -2346,7 +2376,7 @@ char	*parv[];
 	if (IsRegistered(cptr) &&	/* only local query for unregistered */
 	    hunt_server(cptr,sptr,":%s ADMIN :%s",1,parc,parv) != HUNTED_ISME)
 		return 3;
-	if ((aconf = find_admin()) && aconf->host && aconf->passwd
+	if ((aconf = find_conf_one(CONF_ADMIN)) && aconf->host && aconf->passwd
 	    && aconf->name)
 	    {
 		sendto_one(sptr, rpl_str(RPL_ADMINME, parv[0]), ME);
diff -urNp irc2.10.3p7+hemp2/ircd/s_user.c irc2.10.3p7+hemp2+fic/ircd/s_user.c
--- irc2.10.3p7+hemp2/ircd/s_user.c	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/ircd/s_user.c	Thu Aug 26 23:31:55 2004
@@ -39,6 +39,9 @@ static int user_modes[]	     = { FLAGS_O
 				 FLAGS_WALLOP, 'w',
 				 FLAGS_RESTRICTED, 'r',
 				 FLAGS_AWAY, 'a',
+#ifdef IGNORE_STRANGERS
+                 FLAGS_CMODE, 'c',
+#endif
 				 0, 0 };
 
 /*
@@ -630,8 +633,7 @@ char	*nick, *username;
 #endif
 			if (reason)
 				sprintf(buf, "K-lined: %.80s", reason);
-			return exit_client(cptr, sptr, &me, (reason) ? buf :
-					   "K-lined");
+            return ereject_user(cptr, "K-lined", (reason) ? buf : "K-lined");
 		    }
 #ifdef R_LINES
 		if (find_restrict(sptr))
@@ -645,7 +647,7 @@ char	*nick, *username;
 			sendto_flog(sptr, " R lined ", user->username,
 				    user->host);
 # endif
-			return exit_client(cptr, sptr, &me , "R-lined");
+            return ereject_user(cptr, "R-lined", "R-lined");
 		    }
 #endif
 
@@ -1325,7 +1327,17 @@ int	parc, notice;
 				sendto_one(sptr, rpl_str(RPL_AWAY, parv[0]),
 					   acptr->name,
 					   (acptr->user->away) ? 
-					   acptr->user->away : "Gone");
+					   acptr->user->away : DEFAWAY);
+#ifdef IGNORE_STRANGERS
+                if (IsClient(sptr) && !IsAnOper(sptr) && IsIgnoringStrangers(acptr) && (acptr!=sptr) &&
+                    !CommonChannel(sptr->user, acptr->user)) {
+                        if (MyConnect(sptr) && !notice) {
+                            sendto_one(sptr, rpl_str(RPL_AWAY, parv[0]), acptr->name, DEFSTRANGER);
+                        }
+                        continue;
+                }
+#endif
+
 			sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
 					  parv[0], cmd, nick, parv[2]);
 			continue;
@@ -1391,6 +1403,17 @@ int	parc, notice;
 			    !mycmp(user+1, acptr->user->username) &&
 			    !mycmp(host+1, acptr->user->host))
 			    {
+#ifdef IGNORE_STRANGERS
+                if (IsClient(sptr) && !IsAnOper(sptr) && IsIgnoringStrangers(acptr) && (acptr!=sptr) &&
+                    !CommonChannel(sptr->user, acptr->user)) {
+                        if (MyConnect(sptr) && !notice) {
+                            sendto_one(sptr, rpl_str(RPL_AWAY, parv[0]), acptr->name, DEFSTRANGER);
+                        }
+                        *user = '!';
+                        *host = '@';
+                        continue;
+                }
+#endif
 				sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
 						  parv[0], cmd, nick, parv[2]);
 				*user = '!';
@@ -1433,11 +1456,21 @@ int	parc, notice;
 				*--host = '%';
 			if (acptr)
 			    {
-				if (count == 1)
+				if (count == 1) {
+#ifdef IGNORE_STRANGERS
+                if (IsClient(sptr) && !IsAnOper(sptr) && IsIgnoringStrangers(acptr) && (acptr!=sptr) &&
+                    !CommonChannel(sptr->user, acptr->user)) {
+                        if (MyConnect(sptr) && !notice) {
+                            sendto_one(sptr, rpl_str(RPL_AWAY, parv[0]), acptr->name, DEFSTRANGER);
+                        }
+                        continue;
+                }
+#endif
 					sendto_prefix_one(acptr, sptr,
 							  ":%s %s %s :%s",
 					 		  parv[0], cmd,
 							  nick, parv[2]);
+                }
 				else if (!notice)
 					sendto_one(sptr, err_str(
 						   ERR_TOOMANYTARGETS,
@@ -1456,11 +1489,21 @@ int	parc, notice;
 			*--host = '%';
 			if (acptr)
 			    {
-				if (count == 1)
+				if (count == 1) {
+#ifdef IGNORE_STRANGERS
+                if (IsClient(sptr) && !IsAnOper(sptr) && IsIgnoringStrangers(acptr) && (acptr!=sptr) &&
+                    !CommonChannel(sptr->user, acptr->user)) {
+                        if (MyConnect(sptr) && !notice) {
+                            sendto_one(sptr, rpl_str(RPL_AWAY, parv[0]), acptr->name, DEFSTRANGER);
+                        }
+                        continue;
+                }
+#endif
 					sendto_prefix_one(acptr, sptr,
 							  ":%s %s %s :%s",
 					 		  parv[0], cmd,
 							  nick, parv[2]);
+                }
 				else if (!notice)
 					sendto_one(sptr, err_str(
 						   ERR_TOOMANYTARGETS,
@@ -1870,7 +1913,7 @@ aClient	*sptr, *acptr;
 
 	if (user->flags & FLAGS_AWAY)
 		sendto_one(sptr, rpl_str(RPL_AWAY, sptr->name), name,
-			   (user->away) ? user->away : "Gone");
+			   (user->away) ? user->away : DEFAWAY);
 
 	if (IsAnOper(acptr))
 		sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR, sptr->name), name);
@@ -2171,7 +2214,10 @@ char	*parv[];
     {
 	static char comment[TOPICLEN+1];
 
-	if (MyClient(sptr) || MyService(sptr))
+    if (IsServer(sptr))
+         return 0;
+
+	if (MyConnect(sptr))
 	{
 		(void) snprintf(comment, TOPICLEN, "\"%s",
 			(parc > 1 && parv[1]) ? parv[1] : "");
@@ -2182,7 +2228,7 @@ char	*parv[];
 		(void) snprintf(comment, TOPICLEN + 1, "%s",
 			(parc > 1 && parv[1]) ? parv[1] : "");
 	}
-	return IsServer(sptr) ? 0 : exit_client(cptr, sptr, sptr, comment);
+	return exit_client(cptr, sptr, sptr, comment);
     }
 
 /*
diff -urNp irc2.10.3p7+hemp2/support/Makefile.in irc2.10.3p7+hemp2+fic/support/Makefile.in
--- irc2.10.3p7+hemp2/support/Makefile.in	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/support/Makefile.in	Thu Aug 26 23:31:55 2004
@@ -136,8 +136,6 @@ TKSERV = tkserv
 TKSERV_LOGFILE = $(ircd_log_dir)/tkserv.log
 # TK line service access file 
 TKSERV_ACCESSFILE = $(ircd_conf_dir)/tkserv.access
-# IRCD config file without path (from CPATH)
-TKSERV_IRCD_CONF = ircd.conf
 
 # End of system configuration section.
 # ------------------------------------------------------------------------
diff -urNp irc2.10.3p7+hemp2/support/config.h.dist irc2.10.3p7+hemp2+fic/support/config.h.dist
--- irc2.10.3p7+hemp2/support/config.h.dist	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/support/config.h.dist	Thu Aug 26 23:31:55 2004
@@ -559,6 +559,60 @@
 
 /* end of +jv patch */
 
+/*
+ * Use W:line - if client disconnects (not because of himself did
+ * quit) show him the text from W:line - an URL where he can get
+ * more info. IMPORTANT CHANGE: it just works when an unregistered client 
+ * disconnects since 4.8.2004 as the W:line should just show why the client
+ * can't connect.
+ * Requested by fantomas.
+ */
+#define  W_LINE
+
+/*
+ * No comment abuse - if user is not able to speak on some channel he
+ * also can't annoy with his quit/part message. If he parts or does join 0
+ * the part message is changed to "None".
+ * If he quits a part is generated for the channels where he wasn't allowed to
+ * speak first.
+ */
+#define NOCOMMENTABUSE
+
+/*
+ * Ignore strangers - if user has +c mode set just people who share at least
+ * one channel with him can send him messages. Local people (those who are on
+ * the same server as the +c user) also get a DEFSTRANGER reply.
+ * (Thanks jv!)
+ */
+#undef IGNORE_STRANGERS
+
+#define DEFAWAY "Gone"
+/* default away message: "Gone" */
+
+#ifdef IGNORE_STRANGERS
+#define DEFSTRANGER "User is ignoring messages from strangers."
+#endif
+
+/*
+ * Empty comments 
+ * Note: p6 already has empty comments as a default in QUIT and PART!
+ */
+#define EMPTYCOMMENTS
+
+/*
+ * Disable stats L (stats l still works) for non-opers
+ * This is BOFH and should never be used 
+ */
+#undef STATS_L_OPERONLY
+
+/*
+ * AND I:line behavior
+ * Require both IP and hostname field to match in the I:line 
+ */ 
+#define AND_ILINE_BEHAVIOR
+
+/* end of +fiction */
+
 /*   STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP  */
 /*   STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP  */
 /*   STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP  */
diff -urNp irc2.10.3p7+hemp2/support/tkconf.h.dist irc2.10.3p7+hemp2+fic/support/tkconf.h.dist
--- irc2.10.3p7+hemp2/support/tkconf.h.dist	Thu Aug 19 17:49:36 2004
+++ irc2.10.3p7+hemp2+fic/support/tkconf.h.dist	Thu Aug 26 23:31:55 2004
@@ -27,9 +27,20 @@
 /* Debugging (displays service<->server traffic to standard output) */
 #undef TKSERV_DEBUG
 
-/* The name of the ircd config file backup (suffix after CPATH) */
-#define TKSERV_IRCD_CONFIG_BAK 	TKSERV_IRCD_CONF".tkserv"
+/* TKLINE_PATH is like /something/somewhere/some.file */
+#ifdef KLINE_FILE
+#define TKLINE_PATH KLINE_FILE
+#else
+#define TKLINE_PATH CPATH
+#endif
+/* Now ircd.conf is used or the kline file as specified in hemp */
+/* Else the ability from hemp to have klines in different file breaks stuff */
+
+/* The name of the backup of the kline file (full path) */
+#define TKLINE_PATH_BAK        TKLINE_PATH".tkserv"
+
+/* The name of the temporary kline file (full path) */
+#define TKLINE_PATH_TMP        TKLINE_PATH".tmp"
+
 
-/* The name of the ircd temp config file (suffix after CPATH) */
-#define TKSERV_IRCD_CONFIG_TMP	TKSERV_IRCD_CONF".tmp"
 
