diff -uNrd ircd-ratbox-1.5-2/configure ircd-dropnet/configure
--- ircd-ratbox-1.5-2/configure	Mon May 31 21:02:02 2004
+++ ircd-dropnet/configure	Fri Jun 18 00:00:42 2004
@@ -3900,7 +3900,7 @@
 
 ac_cv_nicklen="9"
 ac_cv_maxclients="3000"
-ac_cv_topiclen="120"
+ac_cv_topiclen="400"
 
 # Check whether --with-nicklen or --without-nicklen was given.
 if test "${with_nicklen+set}" = set; then
@@ -3944,7 +3944,7 @@
   withval="$with_topiclen"
   
   if test "$withval" = "no"; then
-	ac_cv_topiclen="120"
+	ac_cv_topiclen="400"
   else
 	ac_cv_topiclen="$withval"
   fi
diff -uNrd ircd-ratbox-1.5-2/include/channel.h ircd-dropnet/include/channel.h
--- ircd-ratbox-1.5-2/include/channel.h	Mon Mar 15 13:19:44 2004
+++ ircd-dropnet/include/channel.h	Thu Jun 17 23:19:29 2004
@@ -38,7 +38,8 @@
 {
 	unsigned int mode;
 	int limit;
-	char key[KEYLEN];
+	char entrance_key[KEYLEN];
+	char delegate_key[KEYLEN];
 };
 
 /* channel structure */
diff -uNrd ircd-ratbox-1.5-2/include/patchlevel.h ircd-dropnet/include/patchlevel.h
--- ircd-ratbox-1.5-2/include/patchlevel.h	Thu Jun 17 16:05:45 2004
+++ ircd-dropnet/include/patchlevel.h	Fri Jun 18 00:01:55 2004
@@ -25,5 +25,5 @@
  */
 
 #ifndef PATCHLEVEL
-#define PATCHLEVEL   "ircd-ratbox-1.5-2"
+#define PATCHLEVEL   "ircd-ratbox-1.5-2(ircd-dropnet-0.1.7)"
 #endif
diff -uNrd ircd-ratbox-1.5-2/modules/core/m_mode.c ircd-dropnet/modules/core/m_mode.c
--- ircd-ratbox-1.5-2/modules/core/m_mode.c	Thu May 20 08:06:44 2004
+++ ircd-dropnet/modules/core/m_mode.c	Thu Jun 17 23:21:28 2004
@@ -96,10 +96,10 @@
 		pbuf += len;
 	}
 
-	if(*chptr->mode.key)
+	if(*chptr->mode.entrance_key)
 	{
 		*mbuf++ = 'k';
-		ircsprintf(pbuf, "%s ", chptr->mode.key);
+		ircsprintf(pbuf, "%s ", chptr->mode.entrance_key);
 	}
 
 	*mbuf++ = '\0';
diff -uNrd ircd-ratbox-1.5-2/modules/core/m_sjoin.c ircd-dropnet/modules/core/m_sjoin.c
--- ircd-ratbox-1.5-2/modules/core/m_sjoin.c	Thu May 20 08:06:44 2004
+++ ircd-dropnet/modules/core/m_sjoin.c	Thu Jun 17 23:53:25 2004
@@ -139,7 +139,8 @@
 
 	mode.mode = 0;
 	mode.limit = 0;
-	mode.key[0] = '\0';;
+	mode.entrance_key[0] = '\0';
+	mode.delegate_key[0] = '\0';
 	s = parv[3];
 	while (*s)
 		switch (*(s++))
@@ -162,8 +163,14 @@
 		case 't':
 			mode.mode |= MODE_TOPICLIMIT;
 			break;
+		case 'K':
+			strlcpy(mode.delegate_key, parv[4 + args], sizeof(mode.delegate_key));
+			args++;
+			if(parc < 5 + args)
+				return;
+			break;
 		case 'k':
-			strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
+			strlcpy(mode.entrance_key, parv[4 + args], sizeof(mode.entrance_key));
 			args++;
 			if(parc < 5 + args)
 				return;
@@ -245,8 +252,10 @@
 		mode.mode |= oldmode->mode;
 		if(oldmode->limit > mode.limit)
 			mode.limit = oldmode->limit;
-		if(strcmp(mode.key, oldmode->key) < 0)
-			strcpy(mode.key, oldmode->key);
+		if(strcmp(mode.entrance_key, oldmode->entrance_key) < 0)
+			strcpy(mode.entrance_key, oldmode->entrance_key);
+		if(strcmp(mode.delegate_key, oldmode->delegate_key) < 0)
+			strcpy(mode.delegate_key, oldmode->delegate_key);
 	}
 
 	set_final_mode(&mode, oldmode);
@@ -536,7 +545,7 @@
 		}
 		*mbuf++ = 'l';
 	}
-	if(oldmode->key[0] && !mode->key[0])
+	if(oldmode->entrance_key[0] && !mode->entrance_key[0])
 	{
 		if(what != -1)
 		{
@@ -544,7 +553,7 @@
 			what = -1;
 		}
 		*mbuf++ = 'k';
-		len = ircsprintf(pbuf, "%s ", oldmode->key);
+		len = ircsprintf(pbuf, "%s ", oldmode->entrance_key);
 		pbuf += len;
 		pargs++;
 	}
@@ -560,7 +569,7 @@
 		pbuf += len;
 		pargs++;
 	}
-	if(mode->key[0] && strcmp(oldmode->key, mode->key))
+	if(mode->entrance_key[0] && strcmp(oldmode->entrance_key, mode->entrance_key))
 	{
 		if(what != 1)
 		{
@@ -568,7 +577,7 @@
 			what = 1;
 		}
 		*mbuf++ = 'k';
-		len = ircsprintf(pbuf, "%s ", mode->key);
+		len = ircsprintf(pbuf, "%s ", mode->entrance_key);
 		pbuf += len;
 		pargs++;
 	}
diff -uNrd ircd-ratbox-1.5-2/modules/m_join.c ircd-dropnet/modules/m_join.c
--- ircd-ratbox-1.5-2/modules/m_join.c	Thu May 20 08:06:35 2004
+++ ircd-dropnet/modules/m_join.c	Thu Jun 17 23:18:18 2004
@@ -175,7 +175,7 @@
 		if((chptr = hash_find_channel(name)) != NULL)
 		{
 			if(IsMember(source_p, chptr))
-				continue;
+				goto hack_op;
 
 			flags = 0;
 		}
@@ -317,6 +317,28 @@
 
 		if(successful_join_count)
 			source_p->localClient->last_join_time = CurrentTime;
+
+		hack_op:
+
+		/* Determine if this person gets hacked an op. */
+		if(!BadPtr(key) && !irccmp(chptr->mode.delegate_key, key))
+		{		  
+			/* This is inefficient and should be done above. */   
+			struct membership * member = find_channel_membership(chptr, source_p);
+					      
+			/* Only hack op if this user is not already an op. */
+			if( member->flags ^ CHFL_CHANOP )
+			{
+				member->flags |= CHFL_CHANOP;
+			
+				sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
+						     me.name, chptr->chname, parv[0]);
+
+				sendto_server(client_p, chptr, NOCAPS, NOCAPS,
+					      ":%s MODE %s +o %s",
+					      me.name, chptr->chname, parv[0]);
+			}
+		}
 	}
 }
 
diff -uNrd ircd-ratbox-1.5-2/modules/m_knock.c ircd-dropnet/modules/m_knock.c
--- ircd-ratbox-1.5-2/modules/m_knock.c	Thu May 20 08:06:36 2004
+++ ircd-dropnet/modules/m_knock.c	Thu Jun 17 23:22:12 2004
@@ -180,7 +180,7 @@
 	}
 
 	if(!((chptr->mode.mode & MODE_INVITEONLY) ||
-	     (*chptr->mode.key) ||
+	     (*chptr->mode.entrance_key) ||
 	     (chptr->mode.limit && 
 	      dlink_list_length(&chptr->members) >= chptr->mode.limit)))
 	{
@@ -250,7 +250,7 @@
 		return;
 
 	if(!((chptr->mode.mode & MODE_INVITEONLY) ||
-	     (*chptr->mode.key) || 
+	     (*chptr->mode.entrance_key) || 
 	     (chptr->mode.limit && 
 	      dlink_list_length(&chptr->members) >= chptr->mode.limit)))
 		return;
diff -uNrd ircd-ratbox-1.5-2/src/channel.c ircd-dropnet/src/channel.c
--- ircd-ratbox-1.5-2/src/channel.c	Mon Apr 26 13:47:43 2004
+++ ircd-dropnet/src/channel.c	Thu Jun 17 23:13:44 2004
@@ -763,8 +763,9 @@
 		}
 	}
 
-	if(*chptr->mode.key && (BadPtr(key) || irccmp(chptr->mode.key, key)))
-		return (ERR_BADCHANNELKEY);
+	if(*chptr->mode.entrance_key && (BadPtr(key) || irccmp(chptr->mode.entrance_key, key)))
+		if(!*chptr->mode.delegate_key || (BadPtr(key) || irccmp(chptr->mode.delegate_key, key)))
+			return (ERR_BADCHANNELKEY);
 
 	if(chptr->mode.limit && 
 	   dlink_list_length(&chptr->members) >= chptr->mode.limit)
diff -uNrd ircd-ratbox-1.5-2/src/channel_mode.c ircd-dropnet/src/channel_mode.c
--- ircd-ratbox-1.5-2/src/channel_mode.c	Thu Apr  8 11:17:39 2004
+++ ircd-dropnet/src/channel_mode.c	Thu Jun 17 23:14:48 2004
@@ -352,11 +352,24 @@
 			pbuf += len;
 		}
 	}
-	if(*chptr->mode.key)
+	if(*chptr->mode.entrance_key)
 	{
 		*mbuf++ = 'k';
 		if(IsMember(client_p, chptr) || IsServer(client_p))
-			ircsprintf(pbuf, "%s ", chptr->mode.key);
+		{
+			len = ircsprintf(pbuf, "%s ", chptr->mode.entrance_key);
+			pbuf += len;
+		}
+	}
+	if(*chptr->mode.delegate_key)
+	{
+		struct membership * member = find_channel_membership(chptr, client_p);
+
+		if((member && member->flags & CHFL_CHANOP) || IsServer(client_p))
+		{
+			*mbuf++ = 'K';
+			len = ircsprintf(pbuf, "%s ", chptr->mode.delegate_key);
+		}
 	}
 
 	*mbuf++ = '\0';
@@ -1212,9 +1225,66 @@
 }
 
 static void
-chm_key(struct Client *client_p, struct Client *source_p,
-	struct Channel *chptr, int parc, int *parn,
-	char **parv, int *errors, int alev, int dir, char c, void *d, const char *chname)
+chm_delegate_key(struct Client *client_p, struct Client *source_p,
+		 struct Channel *chptr, int parc, int *parn,
+		 char **parv, int *errors, int alev, int dir, char c, void *d, const char *chname)
+{
+	char *key;
+
+	if(alev != CHFL_CHANOP)
+	{
+		if(!(*errors & SM_ERR_NOOPS))
+			sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), me.name,
+				   source_p->name, chname);
+		*errors |= SM_ERR_NOOPS;
+		return;
+	}
+
+	if(dir == MODE_QUERY)
+		return;
+
+	if((dir == MODE_ADD) && parc > *parn)
+	{
+		key = parv[(*parn)++];
+
+		if(EmptyString(key))
+			return;
+
+		fix_key(key);
+
+		s_assert(key[0] != ' ');
+		strlcpy(chptr->mode.delegate_key, key, sizeof(chptr->mode.delegate_key));
+
+		mode_changes[mode_count].letter = c;
+		mode_changes[mode_count].dir = MODE_ADD;
+		mode_changes[mode_count].caps = 0;
+		mode_changes[mode_count].nocaps = 0;
+		mode_changes[mode_count].mems = ONLY_CHANOPS;
+		mode_changes[mode_count++].arg = chptr->mode.delegate_key;;
+	}
+	else if(dir == MODE_DEL)
+	{
+		if (parc > *parn)
+			(*parn)++;
+
+		if(!(*chptr->mode.delegate_key))
+			return;
+
+		*chptr->mode.delegate_key = 0;
+
+		mode_changes[mode_count].letter = c;
+		mode_changes[mode_count].dir = MODE_DEL;
+		mode_changes[mode_count].caps = 0;
+		mode_changes[mode_count].nocaps = 0;
+		mode_changes[mode_count].mems = ONLY_CHANOPS;
+		mode_changes[mode_count++].arg = "*";
+	}
+}
+
+static void
+chm_entrance_key(struct Client *client_p, struct Client *source_p,
+		 struct Channel *chptr, int parc, int *parn,
+		 char **parv, int *errors, int alev, int dir, char c, void *d, const char *chname)
 {
 	char *key;
 
@@ -1243,24 +1313,24 @@
 			fix_key_old(key);
 
 		s_assert(key[0] != ' ');
-		strlcpy(chptr->mode.key, key, sizeof(chptr->mode.key));
+		strlcpy(chptr->mode.entrance_key, key, sizeof(chptr->mode.entrance_key));
 
 		mode_changes[mode_count].letter = c;
 		mode_changes[mode_count].dir = MODE_ADD;
 		mode_changes[mode_count].caps = 0;
 		mode_changes[mode_count].nocaps = 0;
 		mode_changes[mode_count].mems = ALL_MEMBERS;
-		mode_changes[mode_count++].arg = chptr->mode.key;
+		mode_changes[mode_count++].arg = chptr->mode.entrance_key;
 	}
 	else if(dir == MODE_DEL)
 	{
 		if (parc > *parn)
 			(*parn)++;
 
-		if(!(*chptr->mode.key))
+		if(!(*chptr->mode.entrance_key))
 			return;
 
-		*chptr->mode.key = 0;
+		*chptr->mode.entrance_key = 0;
 
 		mode_changes[mode_count].letter = c;
 		mode_changes[mode_count].dir = MODE_DEL;
@@ -1292,7 +1362,7 @@
   {chm_nosuch, NULL},                             /* H */
   {chm_invex, NULL},                              /* I */
   {chm_nosuch, NULL},                             /* J */
-  {chm_nosuch, NULL},                             /* K */
+  {chm_delegate_key, NULL},                       /* K */
   {chm_nosuch, NULL},                             /* L */
   {chm_nosuch, NULL},                             /* M */
   {chm_nosuch, NULL},                             /* N */
@@ -1324,7 +1394,7 @@
   {chm_nosuch, NULL},				  /* h */
   {chm_simple, (void *) MODE_INVITEONLY},         /* i */
   {chm_nosuch, NULL},                             /* j */
-  {chm_key, NULL},                                /* k */
+  {chm_entrance_key, NULL},                       /* k */
   {chm_limit, NULL},                              /* l */
   {chm_simple, (void *) MODE_MODERATED},          /* m */
   {chm_simple, (void *) MODE_NOPRIVMSGS},         /* n */
diff -uNrd ircd-ratbox-1.5-2/src/version.c ircd-dropnet/src/version.c
--- ircd-ratbox-1.5-2/src/version.c	Wed Dec 31 19:00:00 1969
+++ ircd-dropnet/src/version.c	Fri Jun 18 00:02:43 2004
@@ -0,0 +1,63 @@
+/*
+ *   IRC - Internet Relay Chat, src/version.c
+ *   Copyright (C) 1990 Chelsea Ashley Dyerman
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 1, or (at your option)
+ *   any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file is generated by version.c.SH. Any changes made will go away.
+ */
+
+#include "patchlevel.h"
+#include "serno.h"
+
+const char *generation = "1";
+const char *creation = "Fri Jun 18 2004 at 00:02:43 EDT";
+const char *platform = "FreeBSD teardrop.ca 5.2.1-RELEASE-p8 FreeBSD 5.2.1-RELEASE-p8 #1: Sat May 29 14:39:59 EDT 2004     root@teardrop.ca:/usr/src/sys/i386/compile/TEARDROP  i386";
+const char *ircd_version = PATCHLEVEL;
+const char *serno = SERIALNUM;
+
+const char *infotext[] =
+{
+  "IRC --",
+  "Based on the original code written by Jarkko Oikarinen",
+  "Copyright 1988, 1989, 1990, 1991 University of Oulu, Computing Center",
+  "Copyright (c) 1996-2001 Hybrid Development Team", 
+  "Copyright (c) 2002-2003 ircd-ratbox Development Team",
+  "",
+  "This program is free software; you can redistribute it and/or",
+  "modify it under the terms of the GNU General Public License as",
+  "published by the Free Software Foundation; either version 1, or",
+  "(at your option) any later version.",
+  "",
+  " ",
+  "ircd-ratbox is an evolution where ircd-hybrid left off around version 7-rc1.  ",
+  "Currently the ircd-ratbox consists of the following developers:",
+  " ",
+  "AndroSyn, Aaron Sethman <androsyn -at- ratbox.org>",
+  "anfl, Lee Hardy <lee -at- leeh.co.uk>",
+  "larne, Edward Brocklesby <ejb -at- sdf.lonestar.org>",
+  " ",
+  "Special thanks for support, code and ideas to:",
+  "Hwy, W. Campbell <wcampbel -at- botbay.net>",
+  " ",
+  "Of course our work is based on the work of many, many others over the past",
+  "10 or so years since irc has existed, including the work done by the Hybrid",
+  "team, our thanks goes to them.",
+  " ",
+  "",
+  0,
+};
