コード例 #1
0
void Snomask::SendMessage(const std::string &message)
{
	if (message != LastMessage)
	{
		this->Flush();
		LastMessage = message;

		std::string desc = this->Description;
		int MOD_RESULT = 0;
		char mysnomask = MySnomask;
		ServerInstance->Logs->Log("snomask", DEFAULT, "%s: %s", desc.c_str(), message.c_str());

		FOREACH_RESULT(I_OnSendSnotice, OnSendSnotice(mysnomask, desc, message));

		LastBlocked = (MOD_RESULT == 1); // 1 blocks the message

		if (!LastBlocked)
		{
			/* Only opers can receive snotices, so we iterate the oper list */
			std::list<User*>::iterator i = ServerInstance->Users->all_opers.begin();

			while (i != ServerInstance->Users->all_opers.end())
			{
				User* a = *i;
				if (IS_LOCAL(a) && a->IsModeSet('s') && a->IsNoticeMaskSet(mysnomask) && !a->quitting)
				{
					a->WriteServ("NOTICE %s :*** %s: %s", a->nick.c_str(), desc.c_str(), message.c_str());
				}

				i++;
			}
		}
	}
	Count++;
}
コード例 #2
0
ファイル: access.cpp プロジェクト: helixum/ircnetwork
static bool HasPriv(const AccessGroup &ag, const ChanAccess *access, const Anope::string &name)
{
	EventReturn MOD_RESULT;
	FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name));
	if (MOD_RESULT == EVENT_ALLOW || access->HasPriv(name))
	{
		typedef std::multimap<const ChanAccess *, const ChanAccess *> path;
		std::pair<path::const_iterator, path::const_iterator> it = ag.path.second.equal_range(access);
		if (it.first != it.second)
			/* check all of the paths for this entry */
			for (; it.first != it.second; ++it.first)
			{
				const ChanAccess *a = it.first->second;
				/* if only one path fully matches then we are ok */
				if (HasPriv(ag, a, name))
					return true;
			}
		else
			/* entry is the end of a chain, all entries match, ok */
			return true;
	}

	/* entry does not match or none of the chains fully match */
	return false;
}
コード例 #3
0
ファイル: access.cpp プロジェクト: helixum/ircnetwork
bool AccessGroup::HasPriv(const Anope::string &name) const
{
	if (this->super_admin)
		return true;
	else if (!ci || ci->GetLevel(name) == ACCESS_INVALID)
		return false;

	/* Privileges prefixed with auto are understood to be given
	 * automatically. Sometimes founders want to not automatically
	 * obtain privileges, so we will let them */
	bool auto_mode = !name.find("AUTO");

	/* Only grant founder privilege if this isn't an auto mode or if they don't match any entries in this group */
	if ((!auto_mode || this->empty()) && this->founder)
		return true;

	EventReturn MOD_RESULT;
	FOREACH_RESULT(OnGroupCheckPriv, MOD_RESULT, (this, name));
	if (MOD_RESULT != EVENT_CONTINUE)
		return MOD_RESULT == EVENT_ALLOW;

	for (unsigned i = this->size(); i > 0; --i)
	{
		ChanAccess *access = this->at(i - 1);

		if (::HasPriv(*this, access, name))
			return true;
	}

	return false;
}
コード例 #4
0
	/* @return 1 to block the command, 0 to allow */
	virtual int OnPreCommand(std::string &command, std::vector<std::string> &parameters, User *user, bool validated, const std::string &original_line) {
		if (!validated || !ghosting) { return 0; }

		if (command == "NICK") {
			if (user->registered != REG_ALL) {
				/* Nick in use, ghosting is on if we reach here so process */
				if (ServerInstance->FindNickOnly(parameters[0])) {
					/* We just let the user keep his UUID nick and fake further
					 * down that the initial NICK was ok. For now just store
					 * their wanted nick.
					 */
					std::string* authnick = new std::string(parameters[0]);
					user->Extend("wantsnick", authnick);
					/* since we cheat here, make them look as if they have passed
					 * REG_NICK checks. HACK warning! Well its all hack this bit :)
					 */
					user->registered = (user->registered | REG_NICK);

					/* if NICK is sent after USER thus making the user fully NICKUSER
					 * regged, we better trigger OnUserRegister since cmd_nick would
					 * normally do this. Since we handle NICK we got to check and do it.
					 */
					if (user->registered == REG_NICKUSER) {
						int MOD_RESULT = 0;
						FOREACH_RESULT(I_OnUserRegister,OnUserRegister(user));
						if (MOD_RESULT > 0) { return 1; }
					}

					/* Dont let inspircd process the command, we just did */
					return 1;
				}
			}
		}
		return 0;
	}
コード例 #5
0
ファイル: m_xmlrpc_main.cpp プロジェクト: xxgrunge/anope196
	void DoCheckAuthentication(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request)
	{
		Anope::string username = request->data.size() > 0 ? request->data[0] : "";
		Anope::string password = request->data.size() > 1 ? request->data[1] : "";

		if (username.empty() || password.empty())
			request->reply("error", "Invalid parameters");
		else
		{
			NickAlias *na = findnick(username);

			if (!na)
				request->reply("error", "Invalid account");
			else
			{
				EventReturn MOD_RESULT;
				FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(NULL, NULL, std::vector<Anope::string>(), na->nc->display, password));
				if (MOD_RESULT == EVENT_ALLOW)
				{
					request->reply("result", "Success");
					request->reply("account", na->nc->display);
				}
				else
					request->reply("error", "Invalid password");
			}
		}
	}
コード例 #6
0
ファイル: cmode_v.cpp プロジェクト: TuSuNaMi/ircd-sakura
std::string ModeChannelVoice::AddVoice(userrec *user,const char* dest,chanrec *chan,int status)
{
	userrec *d = ServerInstance->Modes->SanityChecks(user,dest,chan,status);

	if (d)
	{
		if (IS_LOCAL(user))
		{
			int MOD_RESULT = 0;
			FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user,d,chan,AC_VOICE));

			if (MOD_RESULT == ACR_DENY)
				return "";
			if (MOD_RESULT == ACR_DEFAULT)
			{
				if ((status < STATUS_HOP) && (!ServerInstance->ULine(user->server)))
				{
					user->WriteServ("482 %s %s :You're not a channel (half)operator",user->nick, chan->name);
					return "";
				}
			}
		}

		return ServerInstance->Modes->Grant(d,chan,UCMODE_VOICE);
	}
	return "";
}
コード例 #7
0
ファイル: cmode_o.cpp プロジェクト: thepaul/inspircd-deb
std::string ModeChannelOp::AddOp(User *user,const char* dest,Channel *chan,int status)
{
	User *d = ServerInstance->Modes->SanityChecks(user,dest,chan,status);

	if (d)
	{
		if (IS_LOCAL(user))
		{
			int MOD_RESULT = 0;
			FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user,d,chan,AC_OP));

			if (MOD_RESULT == ACR_DENY)
				return "";
			if (MOD_RESULT == ACR_DEFAULT)
			{
				if ((status < STATUS_OP) && (!ServerInstance->ULine(user->server)))
				{
					user->WriteServ("482 %s %s :You're not a channel operator",user->nick.c_str(), chan->name.c_str());
					return "";
				}
			}
		}

		return ServerInstance->Modes->Grant(d,chan,UCMODE_OP);
	}
	return "";
}
コード例 #8
0
ファイル: cmode_o.cpp プロジェクト: mikebryant/inspircd
std::string ModeChannelOp::DelOp(userrec *user,const char *dest,chanrec *chan,int status)
{
	userrec *d = ServerInstance->Modes->SanityChecks(user,dest,chan,status);

	if (d)
	{
		if (IS_LOCAL(user))
		{
			int MOD_RESULT = 0;
			ServerInstance->Log(DEBUG,"Call OnAccessCheck for AC_DEOP");
			FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user,d,chan,AC_DEOP));

			ServerInstance->Log(DEBUG,"Returns %d",MOD_RESULT);

			if (MOD_RESULT == ACR_DENY)
				return "";
			if (MOD_RESULT == ACR_DEFAULT)
			{
				if ((status < STATUS_OP) && (!ServerInstance->ULine(user->server)) && (IS_LOCAL(user)))
				{
					user->WriteServ("482 %s %s :You are not a channel operator",user->nick, chan->name);
					return "";
				}
			}
		}

		return ServerInstance->Modes->Revoke(d,chan,UCMODE_OP);
	}
	return "";
}
コード例 #9
0
ファイル: cmd_kill.cpp プロジェクト: mikebryant/inspircd
void cmd_kill::Handle (const char** parameters, int pcnt, userrec *user)
{
	userrec *u = ServerInstance->FindNick(parameters[0]);
	char killreason[MAXBUF];
	int MOD_RESULT = 0;

	ServerInstance->Log(DEBUG,"kill: %s %s", parameters[0], parameters[1]);

	if (u)
	{
		ServerInstance->Log(DEBUG, "into kill mechanism");
		FOREACH_RESULT(I_OnKill, OnKill(user, u, parameters[1]));

		if (MOD_RESULT)
		{
			ServerInstance->Log(DEBUG, "A module prevented the kill with result %d", MOD_RESULT);
			return;
		}

		if (!IS_LOCAL(u))
		{
			// remote kill
			ServerInstance->WriteOpers("*** Remote kill by %s: %s!%s@%s (%s)", user->nick, u->nick, u->ident, u->host, parameters[1]);
			snprintf(killreason, MAXQUIT,"[%s] Killed (%s (%s))", ServerInstance->Config->ServerName, user->nick, parameters[1]);
			u->WriteCommonExcept("QUIT :%s", killreason);
			FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason));
			
			user_hash::iterator iter = ServerInstance->clientlist.find(u->nick);

			if (iter != ServerInstance->clientlist.end())
			{
				ServerInstance->Log(DEBUG,"deleting user hash value %d", iter->second);
				ServerInstance->clientlist.erase(iter);
			}

			if (u->registered == REG_ALL)
			{
				u->PurgeEmptyChannels();
			}

			DELETE(u);
		}
		else
		{
			// local kill
			ServerInstance->Log(DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick, ServerInstance->Config->ServerName, user->dhost, user->nick, parameters[1]);
			user->WriteTo(u, "KILL %s :%s!%s!%s (%s)", u->nick, ServerInstance->Config->ServerName, user->dhost, user->nick, parameters[1]);
			ServerInstance->WriteOpers("*** Local Kill by %s: %s!%s@%s (%s)", user->nick, u->nick, u->ident, u->host, parameters[1]);
			snprintf(killreason,MAXQUIT,"Killed (%s (%s))", user->nick, parameters[1]);
			userrec::QuitUser(ServerInstance, u, killreason);
		}
	}
	else
	{
		user->WriteServ( "401 %s %s :No such nick/channel", user->nick, parameters[0]);
	}
}
コード例 #10
0
ファイル: cmd_user.cpp プロジェクト: TuSuNaMi/ircd-sakura
CmdResult cmd_user::Handle (const char** parameters, int pcnt, userrec *user)
{
	/* A user may only send the USER command once */
	if (!(user->registered & REG_USER))
	{
		if (!ServerInstance->IsIdent(parameters[0]))
		{
			/*
			 * RFC says we must use this numeric, so we do. Let's make it a little more nub friendly though. :)
			 *  -- Craig, and then w00t.
			 */
			user->WriteServ("461 %s USER :Your username is not valid",user->nick);
			return CMD_FAILURE;
		}
		else
		{
			/*
			 * The ident field is IDENTMAX+2 in size to account for +1 for the optional
			 * ~ character, and +1 for null termination, therefore we can safely use up to
			 * IDENTMAX here.
			 */
			strlcpy(user->ident, parameters[0], IDENTMAX);
			strlcpy(user->fullname, *parameters[3] ? parameters[3] : "No info", MAXGECOS);
			user->registered = (user->registered | REG_USER);
		}
	}
	else
	{
		user->WriteServ("462 %s :You may not reregister",user->nick);
		return CMD_FAILURE;
	}

	/* parameters 2 and 3 are local and remote hosts, and are ignored */
	if (user->registered == REG_NICKUSER)
	{
		int MOD_RESULT = 0;
		/* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
		if (ServerInstance->next_call > ServerInstance->Time() + ServerInstance->Config->dns_timeout)
			ServerInstance->next_call = ServerInstance->Time() + ServerInstance->Config->dns_timeout;
		FOREACH_RESULT(I_OnUserRegister,OnUserRegister(user));
		if (MOD_RESULT > 0)
			return CMD_FAILURE;

	}

	return CMD_SUCCESS;
}
コード例 #11
0
ファイル: command.cpp プロジェクト: RanadeepPolavarapu/IRCd
void Command::Run(CommandSource &source, const Anope::string &cmdname, const CommandInfo &info, std::vector<Anope::string> &params)
{
	if (this->RequireUser() && !source.GetUser())
		return;

	// Command requires registered users only
	if (!this->AllowUnregistered() && !source.nc)
	{
		source.Reply(NICK_IDENTIFY_REQUIRED);
		if (source.GetUser())
			Log(LOG_NORMAL, "access_denied_unreg", source.service) << "Access denied for unregistered user " << source.GetUser()->GetMask() << " with command " << cmdname;
		return;
	}

	source.command = cmdname;
	source.permission = info.permission;

	EventReturn MOD_RESULT;
	FOREACH_RESULT(OnPreCommand, MOD_RESULT, (source, this, params));
	if (MOD_RESULT == EVENT_STOP)
		return;

	if (params.size() < this->min_params)
	{
		this->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : "");
		return;
	}

	// If the command requires a permission, and they aren't registered or don't have the required perm, DENIED
	if (!info.permission.empty() && !source.HasCommand(info.permission))
	{
		source.Reply(ACCESS_DENIED);
		if (source.GetUser())
			Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for user " << source.GetUser()->GetMask() << " with command " << cmdname;
		return;
	}

	this->Execute(source, params);
	FOREACH_MOD(OnPostCommand, (source, this, params));
}
コード例 #12
0
ファイル: ns_identify.cpp プロジェクト: xxgrunge/anope196
	void Execute(CommandSource &source, const std::vector<Anope::string> &params)
	{
		User *u = source.u;

		const Anope::string &nick = params.size() == 2 ? params[0] : u->nick;
		Anope::string pass = params[params.size() - 1];

		NickAlias *na = findnick(nick);
		if (na && na->nc->HasFlag(NI_SUSPENDED))
			source.Reply(NICK_X_SUSPENDED, na->nick.c_str());
		else if (u->Account() && na && u->Account() == na->nc)
			source.Reply(_("You are already identified."));
		else
		{
			EventReturn MOD_RESULT;
			FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na ? na->nc->display : nick, pass));
			if (MOD_RESULT == EVENT_STOP)
				return;

			if (!na)
				source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
			else if (MOD_RESULT != EVENT_ALLOW)
			{
				Log(LOG_COMMAND, u, this) << "and failed to identify";
				source.Reply(PASSWORD_INCORRECT);
				bad_password(u);
			}
			else
			{
				if (u->IsIdentified())
					Log(LOG_COMMAND, u, this) << "to log out of account " << u->Account()->display;

				Log(LOG_COMMAND, u, this) << "and identified for account " << na->nc->display;
				source.Reply(_("Password accepted - you are now recognized."));
				u->Identify(na);
			}
		}
		return;
	}
コード例 #13
0
ファイル: cmd_nick.cpp プロジェクト: mikebryant/inspircd
void cmd_nick::Handle (const char** parameters, int pcnt, userrec *user)
{
	char oldnick[NICKMAX];

	if (pcnt < 1) 
	{
		ServerInstance->Log(DEBUG,"not enough params for handle_nick");
		return;
	}
	if (!parameters[0])
	{
		ServerInstance->Log(DEBUG,"invalid parameter passed to handle_nick");
		return;
	}
	if (!parameters[0][0])
	{
		ServerInstance->Log(DEBUG,"zero length new nick passed to handle_nick");
		return;
	}
	if (!user)
	{
		ServerInstance->Log(DEBUG,"invalid user passed to handle_nick");
		return;
	}
	if (!user->nick)
	{
		ServerInstance->Log(DEBUG,"invalid old nick passed to handle_nick");
		return;
	}
	if (irc::string(user->nick) == irc::string(parameters[0]))
	{
		/* If its exactly the same, even case, dont do anything. */
		if (!strcmp(user->nick,parameters[0]))
			return;
		/* Its a change of case. People insisted that they should be
		 * able to do silly things like this even though the RFC says
		 * the nick AAA is the same as the nick aaa.
		 */
		ServerInstance->Log(DEBUG,"old nick is new nick, not updating hash (case change only)");
		strlcpy(oldnick, user->nick, NICKMAX - 1);
		int MOD_RESULT = 0;
		FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0]));
		if (MOD_RESULT)
			return;
		if (user->registered == REG_ALL)
			user->WriteCommon("NICK %s",parameters[0]);
		strlcpy(user->nick, parameters[0], NICKMAX - 1);
		FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
		return;
	}
	else
	{
		if ((*parameters[0] == ':') && (*(parameters[0]+1) != 0))
		{
			parameters[0]++;
		}
		char* mq = ServerInstance->XLines->matches_qline(parameters[0]);
		if (mq)
		{
			ServerInstance->WriteOpers("*** Q-Lined nickname %s from %s!%s@%s: %s",parameters[0],user->nick,user->ident,user->host,mq);
			user->WriteServ("432 %s %s :Invalid nickname: %s",user->nick,parameters[0],mq);
			return;
		}
		if ((ServerInstance->FindNick(parameters[0])) && (ServerInstance->FindNick(parameters[0]) != user))
		{
			user->WriteServ("433 %s %s :Nickname is already in use.",user->nick,parameters[0]);
			return;
		}
	}
	if ((!ServerInstance->IsNick(parameters[0])) && (IS_LOCAL(user)))
	{
		user->WriteServ("432 %s %s :Erroneous Nickname",user->nick,parameters[0]);
		return;
	}

	if (user->registered == REG_ALL)
	{
		int MOD_RESULT = 0;
		FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0]));
		if (MOD_RESULT) {
			// if a module returns true, the nick change is silently forbidden.
			return;
		}

		user->WriteCommon("NICK %s",parameters[0]);
		
	}

	strlcpy(oldnick, user->nick, NICKMAX - 1);

	/* change the nick of the user in the users_hash */
	user = user->UpdateNickHash(parameters[0]);
	/* actually change the nick within the record */
	if (!user) return;
	if (!user->nick) return;

	strlcpy(user->nick, parameters[0], NICKMAX - 1);

	ServerInstance->Log(DEBUG,"new nick set: %s",user->nick);
	
	if (user->registered < REG_NICKUSER)
	{
		user->registered = (user->registered | REG_NICK);
		// dont attempt to look up the dns until they pick a nick... because otherwise their pointer WILL change
		// and unless we're lucky we'll get a duff one later on.
		//user->dns_done = (!lookup_dns(user->nick));
		//if (user->dns_done)
		//	ServerInstance->Log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick);

		if (ServerInstance->Config->NoUserDns)
		{
			user->dns_done = true;
		}
		else
		{
			user->StartDNSLookup();
			if (user->dns_done)
				ServerInstance->Log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick);
		}
	}
	if (user->registered == REG_NICKUSER)
	{
		/* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
		FOREACH_MOD(I_OnUserRegister,OnUserRegister(user));
		//ConnectUser(user,NULL);
	}
	if (user->registered == REG_ALL)
	{
		FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
	}
}
コード例 #14
0
ファイル: modes.cpp プロジェクト: RanadeepPolavarapu/IRCd
bool ChannelMode::CanSet(User *u) const
{
	EventReturn MOD_RESULT;
	FOREACH_RESULT(OnCanSet, MOD_RESULT, (u, this));
	return MOD_RESULT != EVENT_STOP;
}
コード例 #15
0
ファイル: cmd_privmsg.cpp プロジェクト: TuSuNaMi/ircd-sakura
CmdResult cmd_privmsg::Handle (const char** parameters, int pcnt, userrec *user)
{
	userrec *dest;
	chanrec *chan;
	CUList except_list;

	user->idle_lastmsg = ServerInstance->Time();
	
	if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0))
		return CMD_SUCCESS;

	if ((parameters[0][0] == '$') && (IS_OPER(user) || ServerInstance->ULine(user->server)))
	{
		int MOD_RESULT = 0;
		std::string temp = parameters[1];
		FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,(void*)parameters[0],TYPE_SERVER,temp,0,except_list));
		if (MOD_RESULT)
			return CMD_FAILURE;
		parameters[1] = temp.c_str();
		// notice to server mask
		const char* servermask = parameters[0] + 1;
		if (match(ServerInstance->Config->ServerName,servermask))
		{
			user->SendAll("PRIVMSG", "%s", parameters[1]);
		}
		FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,(void*)parameters[0],TYPE_SERVER,parameters[1],0,except_list));
		return CMD_SUCCESS;
	}
	char status = 0;
	if ((*parameters[0] == '@') || (*parameters[0] == '%') || (*parameters[0] == '+'))
	{
		status = *parameters[0];
		parameters[0]++;
	}
	if (parameters[0][0] == '#')
	{
		chan = ServerInstance->FindChan(parameters[0]);

		except_list[user] = user->nick;

		if (chan)
		{
			if (IS_LOCAL(user))
			{
				if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
				{
					user->WriteServ("404 %s %s :Cannot send to channel (no external messages)", user->nick, chan->name);
					return CMD_FAILURE;
				}
				if ((chan->IsModeSet('m')) && (chan->GetStatus(user) < STATUS_VOICE))
				{
					user->WriteServ("404 %s %s :Cannot send to channel (+m)", user->nick, chan->name);
					return CMD_FAILURE;
				}
			}
			int MOD_RESULT = 0;

			std::string temp = parameters[1];
			FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,chan,TYPE_CHANNEL,temp,status,except_list));
			if (MOD_RESULT) {
				return CMD_FAILURE;
			}
			parameters[1] = temp.c_str();

			/* Check again, a module may have zapped the input string */
			if (temp.empty())
			{
				user->WriteServ("412 %s :No text to send", user->nick);
				return CMD_FAILURE;
			}

			if (status)
			{
				if (ServerInstance->Config->UndernetMsgPrefix)
				{
					chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%c %s", status, chan->name, status, parameters[1]);
				}
				else
				{
					chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%s", status, chan->name, parameters[1]);
				}
			}
			else 
			{
				chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %s :%s", chan->name, parameters[1]);
			}

			FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,parameters[1],status,except_list));
		}
		else
		{
			/* no such nick/channel */
			user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
			return CMD_FAILURE;
		}
		return CMD_SUCCESS;
	}

	dest = ServerInstance->FindNick(parameters[0]);
	if (dest)
	{
		if (!*parameters[1])
		{
			user->WriteServ("412 %s :No text to send", user->nick);
			return CMD_FAILURE;
		}

		if (IS_AWAY(dest))
		{
			/* auto respond with aweh msg */
			user->WriteServ("301 %s %s :%s",user->nick,dest->nick,dest->awaymsg);
		}

		int MOD_RESULT = 0;
		
		std::string temp = parameters[1];
		FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,dest,TYPE_USER,temp,0,except_list));
		if (MOD_RESULT) {
			return CMD_FAILURE;
		}
		parameters[1] = (char*)temp.c_str();

		if (IS_LOCAL(dest))
		{
			// direct write, same server
			user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick, parameters[1]);
		}

		FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,dest,TYPE_USER,parameters[1],0,except_list));
	}
	else
	{
		/* no such nick/channel */
		user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
		return CMD_FAILURE;
	}
	return CMD_SUCCESS;
}
コード例 #16
0
ファイル: cmd_notice.cpp プロジェクト: thepaul/inspircd-deb
CmdResult CommandNotice::Handle (const std::vector<std::string>& parameters, User *user)
{
    User *dest;
    Channel *chan;

    CUList exempt_list;

    user->idle_lastmsg = ServerInstance->Time();

    if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
        return CMD_SUCCESS;
    if (parameters[0][0] == '$')
    {
        if (!user->HasPrivPermission("users/mass-message"))
            return CMD_SUCCESS;

        int MOD_RESULT = 0;
        std::string temp = parameters[1];
        FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list));
        if (MOD_RESULT)
            return CMD_FAILURE;
        const char* text = temp.c_str();
        const char* servermask = (parameters[0].c_str()) + 1;

        FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
        if (InspIRCd::Match(ServerInstance->Config->ServerName,servermask, NULL))
        {
            user->SendAll("NOTICE", "%s", text);
        }
        FOREACH_MOD(I_OnUserNotice,OnUserNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
        return CMD_SUCCESS;
    }
    char status = 0;
    const char* target = parameters[0].c_str();

    if (ServerInstance->Modes->FindPrefix(*target))
    {
        status = *target;
        target++;
    }
    if (*target == '#')
    {
        chan = ServerInstance->FindChan(target);

        exempt_list[user] = user->nick;

        if (chan)
        {
            if (IS_LOCAL(user))
            {
                if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
                {
                    user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
                    return CMD_FAILURE;
                }
                if ((chan->IsModeSet('m')) && (chan->GetStatus(user) < STATUS_VOICE))
                {
                    user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
                    return CMD_FAILURE;
                }
            }
            int MOD_RESULT = 0;

            std::string temp = parameters[1];
            FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user,chan,TYPE_CHANNEL,temp,status, exempt_list));
            if (MOD_RESULT) {
                return CMD_FAILURE;
            }
            const char* text = temp.c_str();

            if (temp.empty())
            {
                user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
                return CMD_FAILURE;
            }

            FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,exempt_list));

            if (status)
            {
                if (ServerInstance->Config->UndernetMsgPrefix)
                {
                    chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name.c_str(), status, text);
                }
                else
                {
                    chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name.c_str(), text);
                }
            }
            else
            {
                chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
            }

            FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
        }
        else
        {
            /* no such nick/channel */
            user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), target);
            return CMD_FAILURE;
        }
        return CMD_SUCCESS;
    }

    const char* destnick = parameters[0].c_str();

    if (IS_LOCAL(user))
    {
        const char* targetserver = strchr(destnick, '@');

        if (targetserver)
        {
            std::string nickonly;

            nickonly.assign(destnick, 0, targetserver - destnick);
            dest = ServerInstance->FindNickOnly(nickonly);
            if (dest && strcasecmp(dest->server, targetserver + 1))
            {
                /* Incorrect server for user */
                user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
                return CMD_FAILURE;
            }
        }
        else
            dest = ServerInstance->FindNickOnly(destnick);
    }
    else
        dest = ServerInstance->FindNick(destnick);

    if (dest)
    {
        if (parameters[1].empty())
        {
            user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
            return CMD_FAILURE;
        }

        int MOD_RESULT = 0;
        std::string temp = parameters[1];
        FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user,dest,TYPE_USER,temp,0,exempt_list));
        if (MOD_RESULT) {
            return CMD_FAILURE;
        }
        const char* text = temp.c_str();

        FOREACH_MOD(I_OnText,OnText(user,dest,TYPE_USER,text,0,exempt_list));

        if (IS_LOCAL(dest))
        {
            // direct write, same server
            user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
        }

        FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
    }
    else
    {
        /* no such nick/channel */
        user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
        return CMD_FAILURE;
    }

    return CMD_SUCCESS;

}
コード例 #17
0
ファイル: os_session.cpp プロジェクト: xxgrunge/anope196
	void DoAdd(CommandSource &source, const std::vector<Anope::string> &params)
	{
		User *u = source.u;
		Anope::string mask, expiry, limitstr;
		unsigned last_param = 3;

		mask = params.size() > 1 ? params[1] : "";
		if (!mask.empty() && mask[0] == '+')
		{
			expiry = mask;
			mask = params.size() > 2 ? params[2] : "";
			last_param = 4;
		}

		limitstr = params.size() > last_param - 1 ? params[last_param - 1] : "";

		if (params.size() <= last_param)
		{
			this->OnSyntaxError(source, "ADD");
			return;
		}

		Anope::string reason = params[last_param];
		if (last_param == 3 && params.size() > 4)
			reason += " " + params[4];
		if (reason.empty())
		{
			this->OnSyntaxError(source, "ADD");
			return;
		}

		time_t expires = !expiry.empty() ? dotime(expiry) : Config->ExceptionExpiry;
		if (expires < 0)
		{
			source.Reply(BAD_EXPIRY_TIME);
			return;
		}
		else if (expires > 0)
			expires += Anope::CurTime;

		int limit = -1;
		try
		{
			limit = convertTo<int>(limitstr);
		}
		catch (const ConvertException &) { }

		if (limit < 0 || limit > static_cast<int>(Config->MaxSessionLimit))
		{
			source.Reply(_("Invalid session limit. It must be a valid integer greater than or equal to zero and less than \002%d\002."), Config->MaxSessionLimit);
			return;
		}
		else
		{
			if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos)
			{
				source.Reply(_("Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames."));
				return;
			}

			for (std::vector<Exception *>::iterator it = session_service->GetExceptions().begin(), it_end = session_service->GetExceptions().end(); it != it_end; ++it)
			{
				Exception *e = *it;
				if (e->mask.equals_ci(mask))
				{
					if (e->limit != limit)
					{
						e->limit = limit;
						source.Reply(_("Exception for \002%s\002 has been updated to %d."), mask.c_str(), e->limit);
					}
					else
						source.Reply(_("\002%s\002 already exists on the EXCEPTION list."), mask.c_str());
					return;
				}
			}

			Exception *exception = new Exception();
			exception->mask = mask;
			exception->limit = limit;
			exception->reason = reason;
			exception->time = Anope::CurTime;
			exception->who = u->nick;
			exception->expires = expires;

			EventReturn MOD_RESULT;
			FOREACH_RESULT(I_OnExceptionAdd, OnExceptionAdd(exception));
			if (MOD_RESULT == EVENT_STOP)
				delete exception;
			else
			{
				session_service->AddException(exception);
				source.Reply(_("Session limit for \002%s\002 set to \002%d\002."), mask.c_str(), limit);
				if (readonly)
					source.Reply(READ_ONLY_MODE);
			}
		}

		return;
	}
コード例 #18
0
ファイル: cmd_nick.cpp プロジェクト: thepaul/inspircd-deb
/** Handle nick changes from users.
 * NOTE: If you are used to ircds based on ircd2.8, and are looking
 * for the client introduction code in here, youre in the wrong place.
 * You need to look in the spanningtree module for this!
 */
CmdResult CommandNick::Handle (const std::vector<std::string>& parameters, User *user)
{
	std::string oldnick;

	if (parameters[0].empty())
	{
		/* We cant put blanks in the parameters, so for this (extremely rare) issue we just put '*' here. */
		user->WriteNumeric(432, "%s * :Erroneous Nickname", user->nick.empty() ? user->nick.c_str() : "*");
		return CMD_FAILURE;
	}

	if (((!ServerInstance->IsNick(parameters[0].c_str(), ServerInstance->Config->Limits.NickMax))) && (IS_LOCAL(user)))
	{
		if (!allowinvalid)
		{
			if (parameters[0] == "0")
			{
				// Special case, Fake a /nick UIDHERE. Useful for evading "ERR: NICK IN USE" on connect etc.
				std::vector<std::string> p2;
				std::deque<classbase*> dummy;
				p2.push_back(user->uuid);
				this->HandleInternal(1, dummy);
				this->Handle(p2, user);
				this->HandleInternal(0, dummy);
				return CMD_SUCCESS;
			}

			user->WriteNumeric(432, "%s %s :Erroneous Nickname", user->nick.c_str(),parameters[0].c_str());
			return CMD_FAILURE;
		}
	}

	if (assign(user->nick) == parameters[0])
	{
		/* If its exactly the same, even case, dont do anything. */
		if (parameters[0] == user->nick)
		{
			return CMD_SUCCESS;
		}

		/* Its a change of case. People insisted that they should be
		 * able to do silly things like this even though the RFC says
		 * the nick AAA is the same as the nick aaa.
		 */
		oldnick.assign(user->nick, 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
		int MOD_RESULT = 0;
		FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0]));
		if (MOD_RESULT)
			return CMD_FAILURE;
		if (user->registered == REG_ALL)
			user->WriteCommon("NICK %s",parameters[0].c_str());
		user->nick.assign(parameters[0], 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
		user->InvalidateCache();
		FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
		return CMD_SUCCESS;
	}
	else
	{
		/*
		 * Don't check Q:Lines if it's a server-enforced change, just on the off-chance some f*****g *moron*
		 * tries to Q:Line SIDs, also, this means we just get our way period, as it really should be.
		 * Thanks Kein for finding this. -- w00t
		 *
		 * Also don't check Q:Lines for remote nickchanges, they should have our Q:Lines anyway to enforce themselves.
		 *		-- w00t
		 */
		if (!allowinvalid || !IS_LOCAL(user))
		{
			XLine* mq = ServerInstance->XLines->MatchesLine("Q",parameters[0]);
			if (mq)
			{
				if (user->registered == REG_ALL)
				{
					ServerInstance->SNO->WriteToSnoMask('x', "Q-Lined nickname %s from %s!%s@%s: %s", parameters[0].c_str(), user->nick.c_str(), user->ident.c_str(), user->host.c_str(), mq->reason);
				}
				user->WriteNumeric(432, "%s %s :Invalid nickname: %s",user->nick.c_str(), parameters[0].c_str(), mq->reason);
				return CMD_FAILURE;
			}

			if (ServerInstance->Config->RestrictBannedUsers)
			{
				for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++)
				{
					Channel *chan = i->first;
					if (chan->GetStatus(user) < STATUS_VOICE && chan->IsBanned(user))
					{
						user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
						return CMD_FAILURE;
					}
				}
			}
		}

		/*
		 * Uh oh.. if the nickname is in use, and it's not in use by the person using it (doh) --
		 * then we have a potential collide. Check whether someone else is camping on the nick
		 * (i.e. connect -> send NICK, don't send USER.) If they are camping, force-change the
		 * camper to their UID, and allow the incoming nick change.
		 *
		 * If the guy using the nick is already using it, tell the incoming nick change to gtfo,
		 * because the nick is already (rightfully) in use. -- w00t
		 */
		User* InUse = ServerInstance->FindNickOnly(parameters[0]);
		if (InUse && (InUse != user))
		{
			if (InUse->registered != REG_ALL)
			{
				/* force the camper to their UUID, and ask them to re-send a NICK. */
				InUse->WriteTo(InUse, "NICK %s", InUse->uuid.c_str());
				InUse->WriteNumeric(433, "%s %s :Nickname overruled.", InUse->nick.c_str(), InUse->nick.c_str());
				InUse->UpdateNickHash(InUse->uuid.c_str());
				InUse->nick.assign(InUse->uuid, 0, IS_LOCAL(InUse) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
				InUse->InvalidateCache();
				InUse->registered &= ~REG_NICK;
			}
			else
			{
				/* No camping, tell the incoming user  to stop trying to change nick ;p */
				user->WriteNumeric(433, "%s %s :Nickname is already in use.", user->registered >= REG_NICK ? user->nick.c_str() : "*", parameters[0].c_str());
				return CMD_FAILURE;
			}
		}
	}


	int MOD_RESULT = 0;
	FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user, parameters[0]));
	if (MOD_RESULT)
		// if a module returns true, the nick change is silently forbidden.
		return CMD_FAILURE;

	if (user->registered == REG_ALL)
		user->WriteCommon("NICK %s", parameters[0].c_str());

	oldnick.assign(user->nick, 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);

	/* change the nick of the user in the users_hash */
	user = user->UpdateNickHash(parameters[0].c_str());

	/* actually change the nick within the record */
	if (!user)
		return CMD_FAILURE;

	user->nick.assign(parameters[0], 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
	user->InvalidateCache();

	/* Update display nicks */
	for (UCListIter v = user->chans.begin(); v != user->chans.end(); v++)
	{
		CUList* ulist = v->first->GetUsers();
		CUList::iterator i = ulist->find(user);
		if (i != ulist->end())
			i->second = user->nick;
	}

	if (user->registered < REG_NICKUSER)
	{
		user->registered = (user->registered | REG_NICK);
		if (user->registered == REG_NICKUSER)
		{
			/* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
			MOD_RESULT = 0;
			FOREACH_RESULT(I_OnUserRegister,OnUserRegister(user));
			if (MOD_RESULT > 0)
				return CMD_FAILURE;

			// return early to not penalize new users
			return CMD_SUCCESS;
		}
	}

	if (user->registered == REG_ALL)
	{
		user->IncreasePenalty(10);
		FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user, oldnick));
	}

	return CMD_SUCCESS;

}
コード例 #19
0
ファイル: protocol.cpp プロジェクト: xxgrunge/anope196
bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> &params)
{
	const Anope::string &receiver = params.size() > 0 ? params[0] : "";
	Anope::string message = params.size() > 1 ? params[1] : "";

	/* Messages from servers can happen on some IRCds, check for . */
	if (source.empty() || receiver.empty() || message.empty() || source.find('.') != Anope::string::npos)
		return true;

	User *u = finduser(source);

	if (!u)
	{
		Log() << message << ": user record for " << source << " not found";

		BotInfo *bi = findbot(receiver);
		if (bi)
			ircdproto->SendMessage(bi, source, "%s", "Internal error - unable to process request.");

		return true;
	}

	if (receiver[0] == '#')
	{
		Channel *c = findchan(receiver);
		if (c)
		{
			FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, c, message));
		}
	}
	else
	{
		/* If a server is specified (nick@server format), make sure it matches
		 * us, and strip it off. */
		Anope::string botname = receiver;
		size_t s = receiver.find('@');
		if (s != Anope::string::npos)
		{
			Anope::string servername(receiver.begin() + s + 1, receiver.end());
			botname = botname.substr(0, s);
			if (!servername.equals_ci(Config->ServerName))
				return true;
		}
		else if (Config->UseStrictPrivMsg)
		{
			BotInfo *bi = findbot(receiver);
			if (!bi)
				return true;
			Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << source;
			u->SendMessage(bi, _("\"/msg %s\" is no longer supported.  Use \"/msg %s@%s\" or \"/%s\" instead."), receiver.c_str(), receiver.c_str(), Config->ServerName.c_str(), receiver.c_str());
			return true;
		}

		BotInfo *bi = findbot(botname);

		if (bi)
		{
			EventReturn MOD_RESULT;
			FOREACH_RESULT(I_OnBotPrivmsg, OnBotPrivmsg(u, bi, message));
			if (MOD_RESULT == EVENT_STOP)
				return true;

			if (message[0] == '\1' && message[message.length() - 1] == '\1')
			{
				if (message.substr(0, 6).equals_ci("\1PING "))
				{
					Anope::string buf = message;
					buf.erase(buf.begin());
					buf.erase(buf.end() - 1);
					ircdproto->SendCTCP(bi, u->nick, "%s", buf.c_str());
				}
				else if (message.substr(0, 9).equals_ci("\1VERSION\1"))
				{
					Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
					ircdproto->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, enc ? enc->name.c_str() : "unknown", Anope::VersionBuildString().c_str());
				}
				return true;
			}
			
			bi->OnMessage(u, message);
		}
	}

	return true;
}
コード例 #20
0
ファイル: bahamut.cpp プロジェクト: xxgrunge/anope196
	bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> &params)
	{
		Channel *c = findchan(params[1]);
		time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0;
		bool keep_their_modes = true;

		if (!c)
		{
			c = new Channel(params[1], ts);
			c->SetFlag(CH_SYNCING);
		}
		/* Our creation time is newer than what the server gave us */
		else if (c->creation_time > ts)
		{
			c->creation_time = ts;
			c->Reset();
		}
		/* Their TS is newer than ours, our modes > theirs, unset their modes if need be */
		else if (ts > c->creation_time)
			keep_their_modes = false;

		/* If we need to keep their modes, and this SJOIN string contains modes */
		if (keep_their_modes && params.size() >= 4)
		{
			/* Set the modes internally */
			Anope::string modes;
			for (unsigned i = 2; i < params.size(); ++i)
				modes += " " + params[i];
			if (!modes.empty())
				modes.erase(modes.begin());
			c->SetModesInternal(NULL, modes);
		}

		/* For some reason, bahamut will send a SJOIN from the user joining a channel
		 * if the channel already existed
		 */
		if (!c->HasFlag(CH_SYNCING) && params.size() == 2)
		{
			User *u = finduser(source);
			if (!u)
				Log(LOG_DEBUG) << "SJOIN for nonexistant user " << source << " on " << c->name;
			else
			{
				EventReturn MOD_RESULT;
				FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));

				/* Add the user to the channel */
				c->JoinUser(u);

				/* 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)))
				{
					FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
				}
			}
		}
		else
		{
			spacesepstream sep(params[params.size() - 1]);
			Anope::string buf;
			while (sep.GetToken(buf))
			{
				std::list<ChannelMode *> Status;
				char ch;

				/* Get prefixes from the nick */
				while ((ch = ModeManager::GetStatusChar(buf[0])))
				{
					buf.erase(buf.begin());
					ChannelMode *cm = ModeManager::FindChannelModeByChar(ch);
					if (!cm)
					{
						Log() << "Received unknown mode prefix " << cm << " in SJOIN string";
						continue;
					}

					if (keep_their_modes)
						Status.push_back(cm);
				}

				User *u = finduser(buf);
				if (!u)
				{
					Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name;
					continue;
				}

				EventReturn MOD_RESULT;
				FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));

				/* Add the user to the channel */
				c->JoinUser(u);

				/* Update their status internally on the channel
				 * This will enforce secureops etc on the user
				 */
				for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
					c->SetModeInternal(*it, buf);

				/* 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))
					continue;

				FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
			}
		}

		/* Channel is done syncing */
		if (c->HasFlag(CH_SYNCING))
		{
			/* Unset the syncing flag */
			c->UnsetFlag(CH_SYNCING);
			c->Sync();
		}

		return true;
	}
コード例 #21
0
ファイル: log.cpp プロジェクト: Justasic/Navn
/**
 * \fn Log::~Log()
 * \brief Logging destructor, this is where the files are actually written and messages are logged
 */
Log::~Log()
{
	Flux::string LogColor = Config ? Config->LogColor : "\033[0m";
	Flux::string message = Flux::Sanitize(this->buffer.str());

	std::stringstream logstream;

	if(this->u && !this->c)
		message = this->u->nick + " " + message;

	if(this->u && this->c)
		message = this->u->nick + " used " + this->c->name + " " + message;

	EventResult result;
	FOREACH_RESULT(I_OnLog, OnLog(this), result);

	if(result != EVENT_CONTINUE)
		return;

	switch(type)
	{
		case LOG_SILENT:
		case LOG_NORMAL:
			logstream << TimeStamp() << " " << message;
			this->ToFile(logstream);
			break;
		case LOG_THREAD:

			if(protocoldebug)
			{
				logstream << TimeStamp() << " [THREAD] " << message;
				this->ToFile(logstream);
			}

			break;
		case LOG_DEBUG:

			if(protocoldebug)
			{
				logstream << TimeStamp() << " " << message;
				this->ToFile(logstream);
			}

			break;
		case LOG_DEVEL:

			if(!protocoldebug && dev)
			{
				logstream << TimeStamp() << message;
				this->ToFile(logstream);
			}

			break;
		case LOG_RAWIO:

			if(protocoldebug)
			{
				logstream << TimeStamp() << " " << message;
				this->ToFile(logstream);
			}

			break;
		case LOG_CRITICAL:
			logstream << "\033[22;31m" << TimeStamp() << " [CRITICAL] " << message << LogColor;
			this->ToFile(logstream);
			break;
		case LOG_WARN:
			logstream << TimeStamp() << " \033[22;33m[WARNING]" << LogColor << " " << message;
			this->ToFile(logstream);
			break;
		case LOG_MEMORY:

			if(memdebug)
				std::cout << TimeStamp() << " [MEMORY] " << message << std::endl;

			return; // ignore everything else, it doesn't matter
		case LOG_TERMINAL:

			if(InTerm())
				std::cout << this->buffer.str() << std::endl;

			return;
		default:
			Log(LOG_WARN) << "Wtf log case is this?";
			Log(LOG_TERMINAL) << "\033[22;33m[UNDEFINED]" << LogColor << " " << message;
	}
}