diff -ubrN irc2.10.3p6+hemp2/README-jp irc2.10.3p6+hemp2+jp6/README-jp
--- irc2.10.3p6+hemp2/README-jp	1970-01-01 09:00:00.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/README-jp	2004-03-09 18:40:18.000000000 +0900
@@ -0,0 +1,85 @@
+IRC server jp-patched version (2004/03/09 irc2.10.3p6+hemp2+jp6)
+
+  $B$3$N(Bjp-patched version$B$O!"(BIRC server (ftp://ftp.irc.org/irc/server/) $B$K(B
+  $BBP$7$F<g$K0J2<$N$h$&$J5!G=$rIU2C$7$?$b$N$G$9!#(B
+
+   $B!&F|K\8lBP1~(BIRC$B%/%i%$%"%s%H$NB?$/$,;}$C$F$$$kITHw$rJd$&$?$a!"(B
+     $BB?$/$N%1!<%9$G%f!<%6$,ITJX$J>uBV$K$J$k$N$rKI$0$?$a$N5!G=!#(B
+     ($B:G=*E*$K$O!"3F%/%i%$%"%s%H$N<BAu$G2r7h$9$k$Y$-ItJ,!#(B)
+   $B!&(BIRC$B%5!<%P$N85!9$N;EMM$N$?$a$KF|K\8l$rMQ$$$k>e$G%f!<%6$NMxJX@-$,(B
+     $B<:$o$l$F$$$kLL$rItJ,E*$K2r7h$9$k$?$a$N5!G=!#(B
+
+  $B:G?7$N(Bjp6$BHG$K$*$$$F$O!"$$$^$^$G$O%A%c%M%kL>$K;HMQ$9$k$3$H$,$G$-$J$+$C$?!"(B
+  $B$"$k$$$O!";HMQ$K$*$$$F@)8B$5$l$F$$$?!"(BISO-2022-JP$B$K$*$1$k?tI4J8;z$N4A;z$r(B
+  $B%A%c%M%kL>$NCf$G$9$Y$F;HMQ$9$k$3$H$,$G$-$k$h$&$KBP1~$7$F$$$^$9!#(B($B$$$o$f$k(B
+  #$B$,$,(B $BLdBj$X$NBP1~!"$*$h$S!"(B#$B$:$:(B $BLdBj$X$NBP1~!#(B) $B$3$N5!G=$O(Bjp6$BHG0J9_$N(B
+  $BBP1~%5!<%P4V$G$N$_M-8z$H$J$j$^$9$,!"3:Ev$9$k%A%c%M%k$O$A$g$&$I%^%9%/IU(B
+  $B%A%c%M%k(B($BNc$($P!"(B#abc:*.jp$B$J$I(B)$B$HF1$80LCVIU$1$K$J$k$?$a!"F1$8(BIRC$BLVFb$K(B
+  $BHsBP1~%5!<%P$H$N@\B3$,$"$C$F$bAj8_@\B3>e$N%W%m%H%3%k$K1F6A$,$J$$$h$&$K(B
+  $B<BAu$5$l$F$$$^$9!#(B
+
+  $B:#8e$b!"K\BN$N(B irc2.x $B$HL7=b$J$/<B8=2DG=$J5!G=$K$D$$$F2DG=$J8B$j<BAu$r(B
+  $B9T$J$C$F$$$/M=Dj$G$9!#MWK>$d2~A10F$J$I$,$"$j$^$7$?$i$h$m$7$/$*4j$$$7$^$9!#(B
+  $B$^$?!"(Bbug$B>pJs$*$h$SIT6q9g$dLdBjE@$J$I$b2DG=$J8B$jBP1~$7$?$$$H;W$$$^$9$N$G!"(B
+  $B$=$l$i$K$D$$$F$b$_$J$5$^$+$i$N>pJs$r$*BT$A$7$F$*$j$^$9!#(B
+  
+$BJQ99MzNr(B
+
+  jp6 $B"+(B jp5
+      irc2.10.3$BBP1~(B
+      ircd/s_user.c$B$K$*$1$k%A%c%M%kL>@55,2=1L$l$r(Bfix
+      split$B;~$KH/@8$9$k%A%c%M%k%^%9%/4X78$NEAGE1L$l(Bbug$B$r(Bfix
+      GOOD_USERNAME$B$r(B A-Z,a-z,0-9,_,-,. $B$X$HA}2C(B
+      $B$$$o$f$k(B #$B$,$,(B $BLdBj$KBP1~$7$FMxMQ2DG=$X(B
+      $B$$$o$f$k(B #$B$:$:(B $BLdBj$KBP1~$7$FMxMQ2DG=$X(B
+
+  jp5 $B"+(B jp4
+      ircd/channel.c$B$K$*$1$k%A%c%M%kL>@55,2=(Bbug$B$r(Bfix
+
+  jp4 $B"+(B jp3
+      irc2.9.5$BBP1~(B
+      common/send.c$B$K$*$1$k(Bdeliver_it()$B$G$N%(%i!<;~$K%(%i!<>pJs$rJV$9$?$a!"(B
+      common/bsd.c$B$G$N(Bdeliver_it()$B$NLa$jCM$r(B-1$B$G$O$J$/(B-errno$B$rJV$9$h$&$K$7$?!#(B
+
+  jp3 $B"+(B jp2
+      irc2.9.4$BBP1~(B
+      GOOD_USERNAME$B$G$N(Bjp2y1b$BHG$K9g$o$;$?!#(B
+         A-Z,a-z,0-9,_,- $B$NG$0U$NAH$_9g$o$;$G(BOK$B$H4KOB(B
+
+$BCm0U;v9`(B
+
+  $BF~<j@h(B:   http://www.ircnet.jp/dist/server/jp-patch/
+  $B9pCN@h(B:   http://www.ircnet.jp/server/jp-patch/
+  $BO"Mm@h(B:   mailto:jp-patch@ircnet.jp
+
+  $B$3$N(Bjp-patched$BHG$O(B $B5FCO9b9-(B <kick@wide.ad.jp> $B$,:n@.4IM}$7$F$$$^$9!#(B
+  $BIT6q9g$J$I$,$"$j$^$7$?$i(B jp-patch@ircnet.jp $B$^$G$*4j$$$7$^$9!#(B
+  $B:#8e$N>pJs$J$I$O(B http://www.ircnet.jp/server/jp-patch/ $B$G9pCN$9$kM=Dj$G$9!#(B
+
+  $BK\BN5Z$S(Bpatch$B$H$b$K(BGPL$B$K=>$$$^$9!#>\$7$/$O(Bdoc/$B$N2<$NJ8=qN`$r$I$&$>!#(B
+  $B$?$@$7!"$3$N(Bpatch$B$rMxMQ$7$?$b$N$r2~JQ$7$F:FG[I[$9$k>l9g$O!"$3$NJ8=q$r(B
+  $B$=$N$^$^IU$1$k$H$H$b$K(B jp-patch@ircnet.jp $B$^$GO"Mm$r$$$?$@$1$k$H9,$$$G$9!#(B
+  $B2~JQ$J$/$=$N$^$^:FG[I[$9$k>l9g$O<+M3$K$7$F$/$@$5$C$F7k9=$G$9!#(B
+
+$B$=$NB>$N4XO">pJs(B
+
+  JIRCC (Japan Internet-Relay-Chat Club)
+    JIRCC$B$OF|K\$K$*$1$k(BIRC$B$NIa5Z$H(BIRCer$B4V$N8rN.$r$r$O$+$k$?$a$K(B
+    1990$BG/(B3$B7n$K$G$-$?(BIRC$B$N%f!<%62q$G$9!#%a!<%j%s%0%j%9%H$,$"$j!"(B
+    IRC$B$K4X$9$k<o!9$N>pJs8r49$d5DO@$d9pCN$,9T$J$o$l$F$-$F$$$^$9!#(B
+
+      jircc mailing list
+         IRC$BA4HL$K4X$9$k%a!<%j%s%0%j%9%H$G$9!#(B
+         jircc-request@ircnet.jp $B$X%a!<%k$rAw$k$H;22CJ}K!$,(B
+         $B<+F0JVAw$5$l$F$-$^$9!#%a!<%k$NFbMF$O$"$C$F$b6u$G$bBg>fIW$G$9!#(B
+
+  http://www.ircnet.jp/
+    IRC$B$K4X$9$k>pJs$r=8$a$?%Z!<%8$G$9!#(B
+
+$B<U<-(B
+
+  $BK\(Bpatch$B$N3+H/5Z$S(Bdebugging$B$K$*$$$F!"3+H/4D6-$dB?$/$NJX59$rM?$($F$/$l$?(B
+  $B>pJs5;=Q3+H/3t<02q<R5~ET%M%C%H%o!<%/5;=Q8&5f=j(B http://www.tdi.co.jp/
+  $B5Z$S!"$=$N3'MMJ}$K46<U$N0U$rI=$o$7$?$$$H;W$$$^$9!#$^$?!"F0:n3NG'$J$I(B
+  $B<B1?MQ$K:]$7$FMxMQ$5$;$F$$$?$@$$$?(BIRCnet$B!"5Z$S!"$=$NB?$/$N%f!<%6$N3'MMJ}$K(B
+  $BBP$7!"$3$3$K46<U$N0U$rI=$o$7$?$$$H;W$$$^$9!#(B
diff -ubrN irc2.10.3p6+hemp2/common/bsd.c irc2.10.3p6+hemp2+jp6/common/bsd.c
--- irc2.10.3p6+hemp2/common/bsd.c	2004-03-09 17:21:33.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/common/bsd.c	2004-03-09 18:18:54.000000000 +0900
@@ -106,6 +106,10 @@
 	(void)alarm(WRITEWAITDELAY);
 #endif
 	retval = send(cptr->fd, str, len, 0);
+	
+	if (retval < 0)
+		retval = -errno;
+
 	/*
 	** Convert WOULDBLOCK to a return of "0 bytes moved". This
 	** should occur only if socket was non-blocking. Note, that
diff -ubrN irc2.10.3p6+hemp2/common/send.c irc2.10.3p6+hemp2+jp6/common/send.c
--- irc2.10.3p6+hemp2/common/send.c	2004-03-09 17:29:27.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/common/send.c	2004-03-09 18:18:54.000000000 +0900
@@ -345,7 +345,13 @@
 		msg = dbuf_map(&to->sendQ, &len);
 					/* Returns always len > 0 */
 		if ((rlen = deliver_it(to, msg, len)) < 0)
-			return dead_link(to,"Write error to %s, closing link");
+		    {
+			char	linebuf[1024];
+			(void)sprintf(linebuf,
+				      "Write error (%s) to %%s, closing link",
+				      sys_errlist[-rlen]);
+			return dead_link(to, linebuf);
+		    }
 		(void)dbuf_delete(&to->sendQ, rlen);
 		to->lastsq = DBufLength(&to->sendQ)/1024;
 		if (rlen < len) /* ..or should I continue until rlen==0? */
@@ -1058,7 +1064,7 @@
 	    {
 		if (*chptr->chname == '&')
 			return;
-		if ((mask = (char *)rindex(chptr->chname, ':')))
+		if ((mask = get_channelmask(chptr->chname)))
 			mask++;
 	    }
 	else
@@ -1071,6 +1077,8 @@
 			continue;
 		if (!BadPtr(mask) && match(mask, cptr->name))
 			continue;
+		if (!valid_channel(cptr, chptr, 0))
+			continue;
 		if (chptr &&
 		    *chptr->chname == '!' && !(cptr->serv->version & SV_NJOIN))
 			continue;
@@ -1113,7 +1121,7 @@
 	    {
 		if (*chptr->chname == '&')
 			return 0;
-		if ((mask = (char *)rindex(chptr->chname, ':')))
+		if ((mask = get_channelmask(chptr->chname)))
 			mask++;
 	    }
 	else
@@ -1126,6 +1134,8 @@
 			continue;
 		if (!BadPtr(mask) && match(mask, cptr->name))
 			continue;
+		if (!valid_channel(cptr, chptr, 0))
+			continue;
 		if (chptr &&
 		    *chptr->chname == '!' && !(cptr->serv->version & SV_NJOIN))
 			continue;
@@ -1174,7 +1184,7 @@
 	    {
 		if (*chptr->chname == '&')
 			return 0;
-		if ((mask = (char *)rindex(chptr->chname, ':')))
+		if ((mask = get_channelmask(chptr->chname)))
 			mask++;
 	    }
 	else
@@ -1187,6 +1197,8 @@
 			continue;
 		if (!BadPtr(mask) && match(mask, cptr->name))
 			continue;
+		if (!valid_channel(cptr, chptr, 0))
+			continue;
 		if (chptr &&
 		    *chptr->chname == '!' && !(cptr->serv->version & SV_NJOIN))
 			continue;
diff -ubrN irc2.10.3p6+hemp2/common/struct_def.h irc2.10.3p6+hemp2+jp6/common/struct_def.h
--- irc2.10.3p6+hemp2/common/struct_def.h	2004-03-09 17:29:27.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/common/struct_def.h	2004-03-09 18:18:54.000000000 +0900
@@ -172,6 +172,7 @@
 #define FLAGS_EOBWAIT  0x2000000 /* waiting for EOB */
 #endif
 #define	FLAGS_HELD     0x8000000 /* connection held and reconnect try */
+#define	FLAGS_JP      0x10000000 /* jp version */
 
 #define	FLAGS_OPER       0x0001	/* Operator */
 #define	FLAGS_LOCOP      0x0002 /* Local operator -- SRB */
@@ -640,6 +641,7 @@
 	Link	*clist;		/* list of local! connections which are members */
 	time_t	history;	/* channel history (aka channel delay) */
 	time_t	reop;		/* server reop stamp for !channels */
+	int	flags;
 	char	chname[1];
 };
 
diff -ubrN irc2.10.3p6+hemp2/common/support.c irc2.10.3p6+hemp2+jp6/common/support.c
--- irc2.10.3p6+hemp2/common/support.c	2004-03-09 17:29:27.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/common/support.c	2004-03-09 18:18:54.000000000 +0900
@@ -61,6 +61,10 @@
 {
     char *pos = *save;	/* keep last position across calls */
     Reg char *tmp;
+    int flag = 0;
+
+    if (fs[0] == ',' && fs[1] == '\0')
+	flag = 1;
 
     if (str)
 	pos = str;		/* new string scan */
@@ -73,8 +77,25 @@
 
     tmp = pos; 			/* now, keep position of the token */
 
+    if (flag) {
+	flag = 0;
+	while (*pos) {
+	    if (!flag && *pos == ',') {
+		break;
+	    } else if (pos[0] == '\033' && pos[1] == '$' && pos[2] == 'B') {
+		pos += 3;
+		flag = 1;
+	    } else if (pos[0] == '\033' && pos[1] == '(' && pos[2] == 'B') {
+		pos += 3;
+		flag = 0;
+	    } else {
+		pos++;
+	    }
+	}	      
+    } else {
     while (*pos && index(fs, *pos) == NULL)
 	pos++; 			/* skip content of the token */
+    }
 
     if (*pos)
 	*pos++ = '\0';		/* remove first sep after the token */
@@ -862,6 +883,7 @@
 	if (pl)	/* patchlevel */
 		sprintf(ver + strlen(ver), "p%d", pl);
 	strcat(ver,"+hemp2");
+	strcat(ver,"+jp6");
 	return mystrdup(ver);
 }
 #ifndef CLIENTCOMPILE
diff -ubrN irc2.10.3p6+hemp2/ircd/channel.c irc2.10.3p6+hemp2+jp6/ircd/channel.c
--- irc2.10.3p6+hemp2/ircd/channel.c	2004-03-09 17:53:06.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/ircd/channel.c	2004-03-09 18:38:46.000000000 +0900
@@ -47,6 +47,7 @@
 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	int	special_channel __P((char *));
 static	aChannel *get_channel __P((aClient *, char *, int));
 static	int	set_mode __P((aClient *, aClient *, aChannel *, int *, int,\
 				char **, char *,char *));
@@ -544,6 +545,45 @@
 	return 0;
 }
 
+char	*get_channelmask(chname)
+char	*chname;
+{
+	char	*mask;
+
+	mask = rindex(chname, ':');
+	if (mask && !index(mask, '\033'))
+		return mask;
+
+	return NULL;
+}
+
+int	special_channel(chname)
+char	*chname;
+{
+	char *mask;
+
+	mask = rindex(chname, ':');
+	if (mask && index(mask, '\033'))
+		return 1;
+	if (index(chname, ','))
+		return 1;
+
+	return 0;
+}
+
+int	valid_channel(cptr, chptr, chname)
+aClient	*cptr;
+aChannel *chptr;
+char	*chname;
+{
+	if (((chptr && (chptr->flags & FLAGS_JP)) ||
+	     (chname && special_channel(chname))) &&
+	    (!cptr || (IsServer(cptr) && !(cptr->flags & FLAGS_JP))))
+		return 0;
+
+	return 1;
+}
+
 aChannel *find_channel(chname, chptr)
 Reg	char	*chname;
 Reg	aChannel *chptr;
@@ -767,6 +807,8 @@
 
 	if (check_channelmask(&me, cptr, chptr->chname))
 		return;
+	if (!valid_channel(cptr, chptr, 0))
+		return;
 
 	*modebuf = *parabuf = '\0';
 	channel_modes(cptr, modebuf, parabuf, chptr);
@@ -814,6 +856,8 @@
 
 	if (check_channelmask(&me, cptr, chptr->chname) == -1)
 		return;
+	if (!valid_channel(cptr, chptr, 0))
+		return;
 	if (*chptr->chname == '!' && !(cptr->serv->version & SV_NCHAN))
 		return;
 
@@ -920,7 +964,7 @@
 			modebuf[1] = '\0';
 			channel_modes(sptr, modebuf, parabuf, chptr);
 			sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS, parv[0]),
-				   name, modebuf, parabuf);
+				   chptr->chname, modebuf, parabuf);
 			penalty += 1;
 		    }
 		else	/* Check parameters for the channel */
@@ -965,7 +1009,7 @@
 				    {
 					sendto_channel_butserv(chptr, sptr,
 						        ":%s MODE %s %s %s",
-							parv[0], name,
+							parv[0], chptr->chname,
 							modebuf, parabuf);
 #ifdef USE_SERVICES
 					*modebuf = *parabuf = '\0';
@@ -1866,11 +1910,24 @@
 void	clean_channelname(cn)
 Reg	char *cn;
 {
-	for (; *cn; cn++)
-		if (*cn == '\007' || *cn == ' ' || *cn == ',')
-		    {
+  int flag = 0;
+
+  while (*cn) {
+    if (*cn == '\007' || *cn == ' ') {
 			*cn = '\0';
 			return;
+    } else if (!flag && *cn == ',') {
+      *cn = '\0';
+      return;
+    } else if (cn[0] == '\033' && cn[1] == '$' && cn[2] == 'B') {
+      cn += 3;
+      flag = 1;
+    } else if (cn[0] == '\033' && cn[1] == '(' && cn[2] == 'B') {
+      cn += 3;
+      flag = 0;
+    } else {
+      cn++;
+    }
 		    }
 }
 
@@ -1885,7 +1942,7 @@
 
 	if (*chname == '&' && IsServer(cptr))
 		return -1;
-	s = rindex(chname, ':');
+	s = get_channelmask(chname);
 	if (!s)
 		return 0;
 	if ((t = index(s, '\007')))
@@ -1926,6 +1983,8 @@
 	    {
 		len = CHANNELLEN;
 		*(chname+CHANNELLEN) = '\0';
+		if (check_channelmask(cptr, cptr, chname) == -1)
+		    return NULL;
 	    }
 	if ((chptr = find_channel(chname, (aChannel *)NULL)))
 		return (chptr);
@@ -1939,6 +1998,9 @@
 		chptr->prevch = NULL;
 		chptr->nextch = channel;
 		chptr->history = 0;
+		chptr->flags = 0;
+		if (special_channel(chname))
+			chptr->flags = FLAGS_JP;
 		channel = chptr;
 		(void)add_to_channel_hash_table(chname, chptr);
 	    }
@@ -2409,14 +2471,15 @@
 		** notify all users on the channel
 		*/
 		sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s",
-						parv[0], name);
+						parv[0], chptr->chname);
 		if (s && UseModes(name))
 		    {
 			/* no need if user is creating the channel */
 			if (chptr->users != 1)
 				sendto_channel_butserv(chptr, sptr,
 						       ":%s MODE %s +%s %s %s",
-						       cptr->name, name, s,
+						       cptr->name,
+						       chptr->chname, s,
 						       parv[0],
 						       *(s+1)=='v'?parv[0]:"");
 			*--s = '\007';
@@ -2455,7 +2518,8 @@
 		/*
 	        ** notify other servers
 		*/
-		if (index(name, ':') || *chptr->chname == '!') /* compat */
+		if (!valid_channel(0, chptr, 0) || get_channelmask(name)
+		    || *chptr->chname == '!') /* compat */
 			sendto_match_servs(chptr, cptr, ":%s JOIN :%s%s",
 					   parv[0], name, chop);
 		else if (*chptr->chname != '&')
@@ -2603,7 +2667,7 @@
 						     "");
 		/* send join to local users on channel */
 		sendto_channel_butserv(chptr, acptr, ":%s JOIN %s", name,
-				       parv[1]);
+				       chptr->chname);
 		/* build MODE for local users on channel, eventually send it */
 		if (*mbuf)
 		    {
@@ -2635,7 +2699,8 @@
 			case 2:
 				sendto_channel_butserv(chptr, &me,
 					       ":%s MODE %s +%s%c %s %s",
-						       sptr->name, parv[1], 
+						       sptr->name,
+						       chptr->chname,
 						       modebuf, mbuf[1],
 						       parabuf, name);
 				if (mbuf[2])
@@ -2652,7 +2717,8 @@
 			    {
 				sendto_channel_butserv(chptr, &me,
 						       ":%s MODE %s +%s %s",
-						       sptr->name, parv[1],
+						       sptr->name,
+						       chptr->chname,
 						       modebuf, parabuf);
 				cnt = 0;
 			    }
@@ -2661,7 +2727,8 @@
 	/* send eventual MODE leftover */
 	if (cnt)
 		sendto_channel_butserv(chptr, &me, ":%s MODE %s +%s %s",
-				       sptr->name, parv[1], modebuf, parabuf);
+				       sptr->name, chptr->chname,
+				       modebuf, parabuf);
 
 	/* send NJOIN to capable servers */
 	*q = '\0';
@@ -2730,7 +2797,8 @@
 		/*
 		**  Remove user from the old channel (if any)
 		*/
-		if (!index(name, ':') && (*chptr->chname != '!'))
+		if (valid_channel(0, chptr, 0)
+		    && !get_channelmask(name) && (*chptr->chname != '!'))
 		    {	/* channel:*.mask */
 			if (*name != '&')
 			    {
@@ -2755,7 +2823,7 @@
 			sendto_match_servs(chptr, cptr, PartFmt,
 				   	   parv[0], name, comment);
 		sendto_channel_butserv(chptr, sptr, PartFmt,
-				       parv[0], name, comment);
+				       parv[0], chptr->chname, comment);
 		remove_user_from_channel(sptr, chptr);
 	    }
 	if (*buf)
@@ -2847,7 +2915,8 @@
 			    {
 				sendto_channel_butserv(chptr, sptr,
 						":%s KICK %s %s :%s", parv[0],
-						name, who->name, comment);
+						chptr->chname,
+						who->name, comment);
 				/* Don't send &local kicks out */
 				/* Send !channels and #chan:*.els kicks only
 				   to servers that understand those channels.
@@ -2858,7 +2927,9 @@
 				   upon chptr being &channel --Beeth */
 				if (*chptr->chname != '&' &&
 				    *chptr->chname != '!' &&
-				    index(chptr->chname, ':') == NULL) {
+				    !get_channelmask(chptr->chname) &&
+				    valid_channel(0, chptr, 0))
+				    {
 					if (*nickbuf)
 						(void)strcat(nickbuf, ",");
 					(void)strcat(nickbuf, who->name);
@@ -3025,6 +3096,12 @@
 	if (*parv[2] == '&' && !MyClient(acptr))
 		return 1;
 	chptr = find_channel(parv[2], NullChn);
+	if (!valid_channel(acptr->from, chptr, parv[2]))
+	    {
+		sendto_one(sptr, err_str(ERR_BADCHANMASK, parv[0]),
+			   chptr ? chptr->chname : parv[2]);
+		return 1;
+	    }
 
 	if (!chptr)
 	    {
@@ -3190,7 +3267,7 @@
 			if (chptr && ShowChannel(sptr, chptr) && sptr->user)
 			    {
 				rlen += sendto_one(sptr, rpl_str(RPL_LIST,
-						   parv[0]), name,
+						   parv[0]), chptr->chname,
 						   chptr->users, chptr->topic);
 				if (!MyConnect(sptr) && rlen > CHREPLLEN)
 					break;
@@ -3487,6 +3564,7 @@
 	return MAXPENALTY;
 }
 
+
 void	send_user_joins(cptr, user)
 aClient	*cptr, *user;
 {
@@ -3508,9 +3586,11 @@
 		if (*chptr->chname == '!' && !(cptr->serv->version & SV_NCHAN))
 			/* in reality, testing SV_NCHAN here is pointless */
 			continue;
-		if ((mask = rindex(chptr->chname, ':')))
+		if ((mask = get_channelmask(chptr->chname)))
 			if (match(++mask, cptr->name))
 				continue;
+		if (!valid_channel(cptr, chptr, 0))
+			continue;
 		clen = strlen(chptr->chname);
 		if ((clen + len) > (size_t) BUFSIZE - 7)
 		    {
diff -ubrN irc2.10.3p6+hemp2/ircd/channel_ext.h irc2.10.3p6+hemp2+jp6/ircd/channel_ext.h
--- irc2.10.3p6+hemp2/ircd/channel_ext.h	2004-03-09 17:29:27.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/ircd/channel_ext.h	2004-03-09 18:18:54.000000000 +0900
@@ -38,6 +38,8 @@
 EXTERN int is_chan_op __P((aClient *cptr, aChannel *chptr));
 EXTERN int has_voice __P((aClient *cptr, aChannel *chptr));
 EXTERN int can_send __P((aClient *cptr, aChannel *chptr));
+EXTERN char *get_channelmask __P((char *));
+EXTERN int valid_channel __P((aClient *, aChannel *, char *));
 EXTERN aChannel *find_channel __P((Reg char *chname, Reg aChannel *chptr));
 EXTERN void setup_server_channels __P((aClient *mp));
 EXTERN void channel_modes __P((aClient *cptr, Reg char *mbuf, Reg char *pbuf,
diff -ubrN irc2.10.3p6+hemp2/ircd/ircd.c irc2.10.3p6+hemp2+jp6/ircd/ircd.c
--- irc2.10.3p6+hemp2/ircd/ircd.c	2004-03-09 17:29:27.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/ircd/ircd.c	2004-03-09 18:18:54.000000000 +0900
@@ -961,9 +961,8 @@
 	    }
 #endif
 
-#if !defined(CHROOTDIR)
 	(void)setuid((uid_t)euid);
-# if defined(IRC_UID) && defined(IRC_GID)
+#if defined(IRC_UID) && defined(IRC_GID)
 	if ((int)getuid() == 0)
 	    {
 		/* run as a specified user */
@@ -973,8 +972,7 @@
 		(void)setgid(IRC_GID);
 		(void)setuid(IRC_UID);
 	    } 
-# endif
-#endif /*CHROOTDIR/UID/GID*/
+#endif
 
 #if defined(USE_IAUTH)
 	if ((bootopt & BOOT_NOIAUTH) == 0)
diff -ubrN irc2.10.3p6+hemp2/ircd/s_bsd.c irc2.10.3p6+hemp2+jp6/ircd/s_bsd.c
--- irc2.10.3p6+hemp2/ircd/s_bsd.c	2004-03-09 17:53:06.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/ircd/s_bsd.c	2004-03-09 18:38:46.000000000 +0900
@@ -1106,11 +1106,11 @@
 	    }
 	if (!BadPtr(aconf->passwd))
 #ifndef	ZIP_LINKS
-		sendto_one(cptr, "PASS %s %s IRC|%s %s", aconf->passwd,
+		sendto_one(cptr, "PASS %s %s IRC|%s %sj", aconf->passwd,
 			   pass_version, serveropts,
 			   (bootopt & BOOT_STRICTPROT) ? "P" : "");
 #else
-		sendto_one(cptr, "PASS %s %s IRC|%s %s%s", aconf->passwd,
+		sendto_one(cptr, "PASS %s %s IRC|%s %s%sj", aconf->passwd,
 			   pass_version, serveropts,
 			   (bootopt & BOOT_STRICTPROT) ? "P" : "",
 			   (aconf->status == CONF_ZCONNECT_SERVER) ? "Z" : "");
diff -ubrN irc2.10.3p6+hemp2/ircd/s_serv.c irc2.10.3p6+hemp2+jp6/ircd/s_serv.c
--- irc2.10.3p6+hemp2/ircd/s_serv.c	2004-03-09 17:53:06.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/ircd/s_serv.c	2004-03-09 18:38:46.000000000 +0900
@@ -360,6 +360,9 @@
 		    }
 	    }
 
+	if (link && strchr(link, 'j'))	/* jp version */
+		cptr->flags |= FLAGS_JP;
+
 	/* right now, I can't code anything good for this */
 	/* Stop whining, and do it! ;) */
 	if (link && strchr(link, 'Z'))	/* Compression requested */
@@ -795,11 +798,11 @@
 	    {
 		if (bconf->passwd[0])
 #ifndef	ZIP_LINKS
-			sendto_one(cptr, "PASS %s %s IRC|%s %s", bconf->passwd,
-				   pass_version, serveropts,
+			sendto_one(cptr, "PASS %s %s IRC|%s %sj",
+				   bconf->passwd, pass_version, serveropts,
 				   (bootopt & BOOT_STRICTPROT) ? "P" : "");
 #else
-			sendto_one(cptr, "PASS %s %s IRC|%s %s%s",
+			sendto_one(cptr, "PASS %s %s IRC|%s %s%sj",
 				   bconf->passwd, pass_version, serveropts,
 			   (bconf->status == CONF_ZCONNECT_SERVER) ? "Z" : "",
 				   (bootopt & BOOT_STRICTPROT) ? "P" : "");
diff -ubrN irc2.10.3p6+hemp2/ircd/s_user.c irc2.10.3p6+hemp2+jp6/ircd/s_user.c
--- irc2.10.3p6+hemp2/ircd/s_user.c	2004-03-09 17:53:06.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/ircd/s_user.c	2004-03-09 18:38:46.000000000 +0900
@@ -1339,7 +1339,8 @@
 			if (can_send(sptr, chptr) == 0 || IsServer(sptr))
 				sendto_channel_butone(cptr, sptr, chptr,
 						      ":%s %s %s :%s",
-						      parv[0], cmd, nick,
+						      parv[0], cmd,
+						      chptr->chname,
 						      parv[2]);
 			else if (!notice)
 				sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN,
@@ -1627,7 +1628,7 @@
 	for (acptr = client; acptr; acptr = acptr->next)
 	    {
 			
-		if (!IsPerson(acptr))
+		if (!IsPerson(acptr) || IsInvisible(acptr))
 			continue;
 		
 		/* clear the flag */
@@ -1661,6 +1662,49 @@
 		     match(mask, acptr->info) == 0)
 			who_one(sptr, acptr, NULL, NULL);
 	    }
+	
+	/* Now check common channels
+	 * little bit dirty, but at least faster - jv */
+	for (lp = sptr->user->channel; lp ;lp = lp->next)
+	{
+		chptr = lp->value.chptr;
+		if (IsAnonymous(chptr))
+			continue;
+		for (lp2 = chptr->members; lp2 ;lp2 = lp2->next)
+		{
+			acptr = lp2->value.cptr;
+			
+			if (!IsInvisible(acptr) || (acptr->flags & FLAGS_HIDDEN))
+			{
+				continue;
+			}
+			
+			if (oper && !IsAnOper(acptr))
+			{
+				continue;
+			}
+			
+			acptr->flags |= FLAGS_HIDDEN;
+			if (!mask ||
+			     match(mask, acptr->name) == 0 ||
+			     match(mask, acptr->user->username) == 0 ||
+			     match(mask, acptr->user->host) == 0 ||
+			     match(mask, acptr->user->server) == 0 ||
+			     match(mask, acptr->info) == 0)
+				who_one(sptr, acptr, chptr, NULL);
+		
+		}
+	}
+	/* Now we have to cleanup that flag */
+	for (lp = sptr->user->channel; lp ;lp = lp->next)
+	{
+		chptr = lp->value.chptr;
+		for (lp2 = chptr->members; lp2 ;lp2 = lp2->next)
+		{
+			acptr = lp2->value.cptr;
+			acptr->flags &= ~FLAGS_HIDDEN;
+		}
+	}
 }
 
 /*
@@ -1694,6 +1738,7 @@
 	    mask && penalty <= MAXPENALTY;
 		mask = strtoken(&p, NULL, ","))
 	{
+		chptr = NULL;
 		channame = NULL;
 		penalty += 1;
 
@@ -1790,7 +1835,8 @@
 			}
 		}
 		sendto_one(sptr, rpl_str(RPL_ENDOFWHO, parv[0]),
-			   BadPtr(mask) ?  "*" : mask);
+			   BadPtr(mask) ?  "*" :
+			   (chptr ? chptr->chname : mask));
 	}
 	return penalty;
 }
diff -ubrN irc2.10.3p6+hemp2/ircd/version.c.SH.in irc2.10.3p6+hemp2+jp6/ircd/version.c.SH.in
--- irc2.10.3p6+hemp2/ircd/version.c.SH.in	2004-03-09 17:53:06.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/ircd/version.c.SH.in	2004-03-09 18:38:46.000000000 +0900
@@ -107,6 +107,10 @@
 	"Thanks also to those who provide the kind sys admins who let me and",
 	"others continue to develop IRC.",
 	"",
+	"This program is a jp-patched version. The jp-patch was written by",
+	"KIKUCHI Takahiro <kick@wide.ad.jp>. You can find it in",
+	"http://www.ircnet.jp/dist/server/jp-patch/.",
+	"",
 	"[$sumsserv] [$sumchan] [$sumsbsd] [$sumsuser]",
 	"[$sumhash] [$sumsmisc] [$sumircd]",
 	"",
diff -ubrN irc2.10.3p6+hemp2/support/config.h.dist irc2.10.3p6+hemp2+jp6/support/config.h.dist
--- irc2.10.3p6+hemp2/support/config.h.dist	2004-03-09 17:29:27.000000000 +0900
+++ irc2.10.3p6+hemp2+jp6/support/config.h.dist	2004-03-09 18:18:54.000000000 +0900
@@ -98,7 +98,7 @@
  * mode "i" (i == invisible). Invisibility means people dont showup in
  * WHO or NAMES unless they are on the same channel as you.
  */
-#undef	NO_DEFAULT_INVISIBLE
+#define	NO_DEFAULT_INVISIBLE
 
 /* OPER_KILL
  *
@@ -121,7 +121,7 @@
 #undef	OPER_KILL
 #define	OPER_REHASH
 #undef	OPER_RESTART
-#define	OPER_DIE
+#undef	OPER_DIE
 #undef	OPER_REMOTE
 #undef	LOCOP_REHASH
 #undef	LOCOP_RESTART
@@ -271,7 +271,7 @@
  * define this if you want to use crypted passwords for operators in your
  * ircd.conf file. See contrib/mkpasswd/README for more details on this.
  */
-#undef	CRYPT_OPER_PASSWORD
+#define	CRYPT_OPER_PASSWORD
 
 /*
  * If you want to store encrypted passwords in N-lines for server links,
@@ -345,7 +345,7 @@
  * Some people believe a bot can exactly time the delay and don't like it,
  * I think this is a useless concern. -krys
  */
-#undef RANDOM_NDELAY
+#define RANDOM_NDELAY
 
 /*
  * You've read the BOFH saga and you liked it, then define the following.
@@ -391,6 +391,13 @@
 #define SIXBONE_HACK
 
 /*
+ * Defining this will make the server accept a only good username.
+ * (isalnum(c) || strchr("-_.", c))
+ * obsolete. please use RESTRICT_USERNAMES instead.
+ */
+/* #define GOOD_USERNAME */
+
+/*
  * Disclaimer: The following part concerns the Cr-patches. By defining this
  *             you will end up with "no warranty" whatsoever - use at your
  *             own risk.
