--- /dev/null
+From 4c9300ede35310ee5642f34e5ac227bd96fc7384 Mon Sep 17 00:00:00 2001
+From: DukePyrolator <DukePyrolator@anope.org>
+Date: Sun, 4 Sep 2011 15:08:55 +0200
+Subject: [PATCH 07/16] ngircd: Fix handling of JOIN commands
+
+---
+ modules/protocol/ngircd.cpp | 60 +++++++++++++++++++++++++++++++++++++++---
+ 1 files changed, 55 insertions(+), 5 deletions(-)
+
+diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
+index 7f4186e..3024fdd 100644
+--- a/modules/protocol/ngircd.cpp
++++ b/modules/protocol/ngircd.cpp
+@@ -240,16 +240,58 @@ class ngIRCdIRCdMessage : public IRCdMessage
+ {
+ if (!params.empty())
+ {
++ Anope::string channel, mode;
+ size_t pos = params[0].find('\7');
+ if (pos != Anope::string::npos)
+ {
+- Anope::string channel = params[0].substr(0, pos);
+- Anope::string mode = '+' + params[0].substr(pos, params[0].length()) + " " + source;
+- do_join(source, channel, "");
+- do_cmode(source, channel, mode, "");
++ channel = params[0].substr(0, pos);
++ mode = '+' + params[0].substr(pos+1, params[0].length()) + " " + source;
+ }
+ else
+- do_join(source, params[0], "");
++ channel = params[0];
++
++ Channel *c = findchan(channel);
++
++ if (!c)
++ {
++ c = new Channel(channel, Anope::CurTime);
++ c->SetFlag(CH_SYNCING);
++ }
++
++ User *u = finduser(source);
++
++ if (!u)
++ {
++ Log(LOG_DEBUG) << "JOIN for nonexistant user " << source << " on " << channel;
++ return false;
++ }
++
++ EventReturn MOD_RESULT;
++ FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));
++
++ /* Add the user to the channel */
++ c->JoinUser(u);
++
++ /* set the usermodes to the channel */
++ do_cmode(source, channel, mode, "");
++
++ /* Now set whatever modes this user is allowed to have on the channel */
++ chan_set_correct_modes(u, c, 1);
++
++ /* Check to see if modules want the user to join, if they do
++ * check to see if they are allowed to join (CheckKick will kick/ban them)
++ * Don't trigger OnJoinChannel event then as the user will be destroyed
++ */
++ if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u))
++ return false;
++
++ FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
++
++ if (c->HasFlag(CH_SYNCING))
++ {
++ c->UnsetFlag(CH_SYNCING);
++ c->Sync();
++ }
+ }
+ return true;
+ }
+@@ -491,7 +533,15 @@ class ProtongIRCd : public Module
+ pmodule_ircd_message(&this->ircd_message);
+
+ this->AddModes();
++
++ ModuleManager::Attach(I_OnUserNickChange, this);
+ }
++
++ void OnUserNickChange(User *u, const Anope::string &)
++ {
++ u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED));
++ }
++
+ };
+
+ MODULE_INIT(ProtongIRCd)
+--
+1.7.8.3
+