+bool ModeParser::AddModeWatcher(ModeWatcher* mw)
+{
+ unsigned char mask = 0;
+ unsigned char pos = 0;
+
+ if (!mw)
+ return false;
+
+ if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
+ return false;
+
+ mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
+ pos = (mw->GetModeChar()-65) | mask;
+
+ modewatchers[pos].push_back(mw);
+
+ return true;
+}
+
+bool ModeParser::DelModeWatcher(ModeWatcher* mw)
+{
+ unsigned char mask = 0;
+ unsigned char pos = 0;
+
+ if (!mw)
+ return false;
+
+ if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
+ return false;
+
+ mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
+ pos = (mw->GetModeChar()-65) | mask;
+
+ ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw);
+
+ if (a == modewatchers[pos].end())
+ {
+ return false;
+ }
+
+ modewatchers[pos].erase(a);
+
+ return true;
+}
+
+/** This default implementation can remove simple user modes
+ */
+void ModeHandler::RemoveMode(userrec* user)
+{
+ char moderemove[MAXBUF];
+ const char* parameters[] = { user->nick, moderemove };
+
+ if (user->IsModeSet(this->GetModeChar()))
+ {
+ sprintf(moderemove,"-%c",this->GetModeChar());
+ ServerInstance->Parser->CallHandler("MODE", parameters, 2, user);
+ }
+}
+
+/** This default implementation can remove simple channel modes
+ * (no parameters)
+ */
+void ModeHandler::RemoveMode(chanrec* channel)
+{
+ char moderemove[MAXBUF];
+ const char* parameters[] = { channel->name, moderemove };
+
+ if (channel->IsModeSet(this->GetModeChar()))
+ {
+ userrec* n = new userrec(ServerInstance);
+
+ sprintf(moderemove,"-%c",this->GetModeChar());
+ n->SetFd(FD_MAGIC_NUMBER);
+
+ ServerInstance->SendMode(parameters, 2, n);
+
+ delete n;
+ }
+}
+
+ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
+{
+ struct Initializer
+ {
+ char modechar;
+ ModeHandler* handler;
+ };
+
+ Initializer modes[] = {
+ { 's', new ModeChannelSecret(Instance) },
+ { 'p', new ModeChannelPrivate(Instance) },
+ { 'm', new ModeChannelModerated(Instance) },
+ { 't', new ModeChannelTopicOps(Instance) },
+ { 'n', new ModeChannelNoExternal(Instance) },
+ { 'i', new ModeChannelInviteOnly(Instance) },
+ { 'k', new ModeChannelKey(Instance) },
+ { 'l', new ModeChannelLimit(Instance) },
+ { 'b', new ModeChannelBan(Instance) },
+ { 'o', new ModeChannelOp(Instance) },
+ { 'h', new ModeChannelHalfOp(Instance) },
+ { 'v', new ModeChannelVoice(Instance) },
+ { 's', new ModeUserServerNotice(Instance) },
+ { 'w', new ModeUserWallops(Instance) },
+ { 'i', new ModeUserInvisible(Instance) },
+ { 'o', new ModeUserOperator(Instance) },
+ { 'n', new ModeUserServerNoticeMask(Instance) },
+ { 0, NULL }
+ };
+
+ /* Clear mode list */
+ memset(modehandlers, 0, sizeof(modehandlers));
+ memset(modewatchers, 0, sizeof(modewatchers));
+
+ /* Last parse string */
+ LastParse = "";
+
+ /* Initialise the RFC mode letters */
+ for (int index = 0; modes[index].modechar; index++)
+ this->AddMode(modes[index].handler, modes[index].modechar);
+}