diff -r 972de6ab7b60 help.conf
--- a/help.conf	Sun Jul 18 19:00:03 2010 -0400
+++ b/help.conf	Tue Jul 20 19:36:39 2010 -0400
@@ -217,6 +217,10 @@
 	"         |               | Example:                                                ";
 	"         |               | +bb ~n:*!*@*.aol.com ~n:nick*!*@*                       ";
 	"-----------------------------------------------------------------------------------";
+	"         |               | If a user's matches this, he may not join the channel   ";
+	"    ~r   |     join      | He may perform all other activities if he is already on ";
+	"         |               | the channel, such as speaking and changing his nick.    ";
+	"-----------------------------------------------------------------------------------";
 	"         |               | If the user is in this channel then (s)he is unable to  ";
 	"         |   [prefix]    | join. A prefix can also be specified (+/%/@/&/~) which  ";
 	"    ~c   |    channel    | means that it will only match if the user has that      ";
diff -r 972de6ab7b60 include/h.h
--- a/include/h.h	Sun Jul 18 19:00:03 2010 -0400
+++ b/include/h.h	Tue Jul 20 19:36:39 2010 -0400
@@ -193,7 +193,7 @@
 #ifndef DISABLE_EXTBAN_STACKING
 extern int ban_check_mask(aClient *, aChannel *, char *, int, int);
 extern int extban_is_ok_nuh_extban(aClient *, aChannel *, char *, int, int, int);
-extern char* extban_conv_param_nuh_extban(char *);
+extern char* extban_conv_param_nuh_or_extban(char *);
 #endif
 extern Ban *is_banned(aClient *, aChannel *, int);
 extern Ban *is_banned_with_nick(aClient *, aChannel *, int, char *);
diff -r 972de6ab7b60 src/extbans.c
--- a/src/extbans.c	Sun Jul 18 19:00:03 2010 -0400
+++ b/src/extbans.c	Tue Jul 20 19:36:39 2010 -0400
@@ -275,6 +275,23 @@
 #endif
 }
 
+/* a ban that affects JOINs only */
+int extban_modej_is_banned(aClient *sptr, aChannel *chptr, char *banin, int type)
+{
+	char *sub_ban;
+
+	if (type != BANCHK_JOIN)
+		return 0;
+
+	sub_ban = banin + 3;
+
+#ifdef DISABLE_STACKED_EXTBANS
+	return extban_is_banned_helper(sub_ban);
+#else
+	return ban_check_mask(sptr, chptr, sub_ban, type, 0);
+#endif
+}
+
 #ifndef DISABLE_STACKED_EXTBANS
 /** General is_ok for n!u@h stuff that also deals with recursive extbans.
  */
@@ -455,6 +472,17 @@
 	ExtbanAdd(NULL, req);
 
 	memset(&req, 0, sizeof(ExtbanInfo));
+	req.flag = 'j';
+#ifdef DISABLE_STACKED_EXTBANS
+	req.conv_param = extban_conv_param_nuh;
+#else
+	req.conv_param = extban_conv_param_nuh_or_extban;
+#endif
+	req.is_banned = extban_modej_is_banned;
+	req.is_ok = extban_is_ok_nuh_extban;
+	ExtbanAdd(NULL, req);
+
+	memset(&req, 0, sizeof(ExtbanInfo));
 	req.flag = 'n';
 #ifdef DISABLE_STACKED_EXTBANS
 	req.conv_param = extban_conv_param_nuh;
