Exemplo n.º 1
0
	ModuleSQLAuth(InspIRCd* Me)
	: Module(Me) {
		ServerInstance->Modules->UseInterface("SQLutils");
		ServerInstance->Modules->UseInterface("SQL");

		SQLutils = ServerInstance->Modules->Find("m_sqlutils.so");
		if (!SQLutils)
			throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth_extended.so.");

		SQLprovider = ServerInstance->Modules->FindFeature("SQL");
		if (!SQLprovider)
			throw ModuleException("Can't find an SQL provider module. Please load one before attempting to load m_sqlauth_extended.so.");

		m_customtitle = ServerInstance->Modules->Find("m_customtitle.so");
		/*
		Don't force users to have this module compiled, this module can function without it
		if (!m_customtitle)
			throw ModuleException("Can't find m_customtitle.so. Please load m_customtitle.so before m_sqlauth_extended.so.");
		*/

		OnRehash(NULL);
		Implementation eventlist[] = { I_OnPostConnect, I_OnPreCommand, I_OnUserConnect, I_OnUserDisconnect, I_OnCheckReady, I_OnRequest, I_OnRehash, I_OnUserRegister };
		ServerInstance->Modules->Attach(eventlist, this, 8);

	}
Exemplo n.º 2
0
		void ReadConfig()
		{
			helpop_map.clear();

			ConfigTagList tags = ServerInstance->Config->ConfTags("helpop");
			for(ConfigIter i = tags.first; i != tags.second; ++i)
			{
				ConfigTag* tag = i->second;
				irc::string key = assign(tag->getString("key"));
				std::string value;
				tag->readString("value", value, true); /* Linefeeds allowed */

				if (key == "index")
				{
					throw ModuleException("m_helpop: The key 'index' is reserved for internal purposes. Please remove it.");
				}

				helpop_map[key] = value;
			}

			if (helpop_map.find("start") == helpop_map.end())
			{
				// error!
				throw ModuleException("m_helpop: Helpop file is missing important entry 'start'. Please check the example conf.");
			}
			else if (helpop_map.find("nohelp") == helpop_map.end())
			{
				// error!
				throw ModuleException("m_helpop: Helpop file is missing important entry 'nohelp'. Please check the example conf.");
			}

		}
Exemplo n.º 3
0
void ModuleManager::AddService(ServiceProvider& item)
{
	switch (item.service)
	{
		case SERVICE_COMMAND:
			if (!ServerInstance->Parser->AddCommand(static_cast<Command*>(&item)))
				throw ModuleException("Command "+std::string(item.name)+" already exists.");
			return;
		case SERVICE_MODE:
			if (!ServerInstance->Modes->AddMode(static_cast<ModeHandler*>(&item)))
				throw ModuleException("Mode "+std::string(item.name)+" already exists.");
			return;
		case SERVICE_METADATA:
			if (!ServerInstance->Extensions.Register(static_cast<ExtensionItem*>(&item)))
				throw ModuleException("Extension " + std::string(item.name) + " already exists.");
			return;
		case SERVICE_DATA:
		case SERVICE_IOHOOK:
		{
			DataProviders.insert(std::make_pair(item.name, &item));
			std::string::size_type slash = item.name.find('/');
			if (slash != std::string::npos)
			{
				DataProviders.insert(std::make_pair(item.name.substr(0, slash), &item));
				DataProviders.insert(std::make_pair(item.name.substr(slash + 1), &item));
			}
			return;
		}
		default:
			throw ModuleException("Cannot add unknown service type");
	}
}
Exemplo n.º 4
0
		virtual void ReadConfig()
		{
			ConfigReader *MyConf = new ConfigReader(ServerInstance);

			helpop_map.clear();

			for (int i = 0; i < MyConf->Enumerate("helpop"); i++)
			{
				irc::string key = assign(MyConf->ReadValue("helpop", "key", i));
				std::string value = MyConf->ReadValue("helpop", "value", i, true); /* Linefeeds allowed! */

				if (key == "index")
				{
					throw ModuleException("m_helpop: The key 'index' is reserved for internal purposes. Please remove it.");
				}

				helpop_map[key] = value;
			}

			if (helpop_map.find("start") == helpop_map.end())
			{
				// error!
				throw ModuleException("m_helpop: Helpop file is missing important entries. Please check the example conf.");
			}
			else if (helpop_map.find("nohelp") == helpop_map.end())
			{
				// error!
				throw ModuleException("m_helpop: Helpop file is missing important entries. Please check the example conf.");
			}

		}
Exemplo n.º 5
0
	MSRSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
		, commandmsrsend(this)
	{
		if (!MemoServ::service)
			throw ModuleException("No MemoServ!");
		throw ModuleException("XXX");
	}
Exemplo n.º 6
0
	ModuleSQLite3(InspIRCd* Me)
	: Module(Me), currid(0)
	{
		ServerInstance->Modules->UseInterface("SQLutils");

		if (!ServerInstance->Modules->PublishFeature("SQL", this))
		{
			throw ModuleException("m_sqlite3: Unable to publish feature 'SQL'");
		}

		/* Create a socket on a random port. Let the tcp stack allocate us an available port */
#ifdef IPV6
		listener = new SQLiteListener(this, ServerInstance, 0, "::1");
#else
		listener = new SQLiteListener(this, ServerInstance, 0, "127.0.0.1");
#endif

		if (listener->GetFd() == -1)
		{
			ServerInstance->Modules->DoneWithInterface("SQLutils");
			throw ModuleException("m_sqlite3: unable to create ITC pipe");
		}
		else
		{
			ServerInstance->Logs->Log("m_sqlite3", DEBUG, "SQLite: Interthread comms port is %d", listener->GetPort());
		}

		ReadConf();

		ServerInstance->Modules->PublishInterface("SQL", this);
		Implementation eventlist[] = { I_OnRequest, I_OnRehash };
		ServerInstance->Modules->Attach(eventlist, this, 2);
	}
Exemplo n.º 7
0
	ModuleRandQuote(InspIRCd* Me)
		: Module(Me)
	{

		conf = new ConfigReader(ServerInstance);
		// Sort the Randomizer thingie..
		srand(ServerInstance->Time());

		q_file = conf->ReadValue("randquote","file",0);
		prefix = conf->ReadValue("randquote","prefix",0);
		suffix = conf->ReadValue("randquote","suffix",0);

		mycommand = NULL;

		if (q_file.empty())
		{
			throw ModuleException("m_randquote: Quotefile not specified - Please check your config.");
		}

		quotes = new FileReader(ServerInstance, q_file);
		if(!quotes->Exists())
		{
			throw ModuleException("m_randquote: QuoteFile not Found!! Please check your config - module will not function.");
		}
		else
		{
			/* Hidden Command -- Mode clients assume /quote sends raw data to an IRCd >:D */
			mycommand = new CommandRandquote(ServerInstance);
			ServerInstance->AddCommand(mycommand);
		}
		Implementation eventlist[] = { I_OnUserConnect };
		ServerInstance->Modules->Attach(eventlist, this, 1);
	}
Exemplo n.º 8
0
void ModeParser::AddMode(ModeHandler* mh)
{
	/* Yes, i know, this might let people declare modes like '_' or '^'.
	 * If they do that, thats their problem, and if i ever EVER see an
	 * official InspIRCd developer do that, i'll beat them with a paddle!
	 */
	if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
		throw ModuleException("Invalid letter for mode " + mh->name);

	/* A mode prefix of ',' is not acceptable, it would f**k up server to server.
	 * A mode prefix of ':' will f**k up both server to server, and client to server.
	 * A mode prefix of '#' will mess up /whois and /privmsg
	 */
	PrefixMode* pm = mh->IsPrefixMode();
	if (pm)
	{
		if ((pm->GetPrefix() > 126) || (pm->GetPrefix() == ',') || (pm->GetPrefix() == ':') || (pm->GetPrefix() == '#'))
			throw ModuleException("Invalid prefix for mode " + mh->name);

		if (FindPrefix(pm->GetPrefix()))
			throw ModuleException("Prefix already exists for mode " + mh->name);
	}

	ModeHandler*& slot = modehandlers[mh->GetModeType()][mh->GetModeChar()-65];
	if (slot)
		throw ModuleException("Letter is already in use for mode " + mh->name);

	// The mode needs an id if it is either a user mode, a simple mode (flag) or a parameter mode.
	// Otherwise (for listmodes and prefix modes) the id remains MODEID_MAX, which is invalid.
	ModeHandler::Id modeid = MODEID_MAX;
	if ((mh->GetModeType() == MODETYPE_USER) || (mh->IsParameterMode()) || (!mh->IsListMode()))
		modeid = AllocateModeId(mh->GetModeType());

	if (!modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)).second)
		throw ModuleException("Mode name already in use: " + mh->name);

	// Everything is fine, add the mode

	// If we allocated an id for this mode then save it and put the mode handler into the slot
	if (modeid != MODEID_MAX)
	{
		mh->modeid = modeid;
		modehandlersbyid[mh->GetModeType()][modeid] = mh;
	}

	slot = mh;
	if (pm)
		mhlist.prefix.push_back(pm);
	else if (mh->IsListModeBase())
		mhlist.list.push_back(mh->IsListModeBase());

	RecreateModeListFor004Numeric();
}
Exemplo n.º 9
0
	IdentRequestSocket(LocalUser* u) : user(u)
	{
		age = ServerInstance->Time();

		SetFd(socket(user->server_sa.sa.sa_family, SOCK_STREAM, 0));

		if (GetFd() == -1)
			throw ModuleException("Could not create socket");

		done = false;

		irc::sockets::sockaddrs bindaddr;
		irc::sockets::sockaddrs connaddr;

		memcpy(&bindaddr, &user->server_sa, sizeof(bindaddr));
		memcpy(&connaddr, &user->client_sa, sizeof(connaddr));

		if (connaddr.sa.sa_family == AF_INET6)
		{
			bindaddr.in6.sin6_port = 0;
			connaddr.in6.sin6_port = htons(113);
		}
		else
		{
			bindaddr.in4.sin_port = 0;
			connaddr.in4.sin_port = htons(113);
		}

		/* Attempt to bind (ident requests must come from the ip the query is referring to */
		if (SocketEngine::Bind(GetFd(), bindaddr) < 0)
		{
			this->Close();
			throw ModuleException("failed to bind()");
		}

		SocketEngine::NonBlocking(GetFd());

		/* Attempt connection (nonblocking) */
		if (SocketEngine::Connect(this, &connaddr.sa, connaddr.sa_size()) == -1 && errno != EINPROGRESS)
		{
			this->Close();
			throw ModuleException("connect() failed");
		}

		/* Add fd to socket engine */
		if (!SocketEngine::AddFd(this, FD_WANT_NO_READ | FD_WANT_POLL_WRITE))
		{
			this->Close();
			throw ModuleException("out of fds");
		}
	}
Exemplo n.º 10
0
	ProtoCharybdis(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR)
		, ircd_proto(this)
		, message_away(this)
		, message_capab(this)
		, message_error(this)
		, message_invite(this)
		, message_kick(this)
		, message_kill(this)
		, message_mode(this)
		, message_motd(this)
		, message_notice(this)
		, message_part(this)
		, message_ping(this)
		, message_privmsg(this)
		, message_quit(this)
		, message_squit(this)
		, message_stats(this)
		, message_time(this)
		, message_topic(this)
		, message_version(this)
		, message_whois(this)

		, message_bmask("IRCDMessage", "charybdis/bmask", "ratbox/bmask")
		, message_join("IRCDMessage", "charybdis/join", "ratbox/join")
		, message_nick("IRCDMessage", "charybdis/nick", "ratbox/nick")
		, message_pong("IRCDMessage", "charybdis/pong", "ratbox/pong")
		, message_sid("IRCDMessage", "charybdis/sid", "ratbox/sid")
		, message_sjoin("IRCDMessage", "charybdis/sjoin", "ratbox/sjoin")
		, message_tb("IRCDMessage", "charybdis/tb", "ratbox/tb")
		, message_tmode("IRCDMessage", "charybdis/tmode", "ratbox/tmode")
		, message_uid("IRCDMessage", "charybdis/uid", "ratbox/uid")

		, message_encap(this)
		, message_euid(this)
		, message_pass(this)
		, message_server(this)

	{


		if (ModuleManager::LoadModule("ratbox", User::Find(creator)) != MOD_ERR_OK)
			throw ModuleException("Unable to load ratbox");
		m_ratbox = ModuleManager::FindModule("ratbox");
		if (!m_ratbox)
			throw ModuleException("Unable to find ratbox");
		if (!ratbox)
			throw ModuleException("No protocol interface for ratbox");

		this->AddModes();
	}
Exemplo n.º 11
0
	EOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR)
		, EventHook<Event::Encrypt>(this)
		, EventHook<Event::CheckAuthentication>(this)
		, oldmd5provider(this)
		, md5("md5")
	{
		if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
			throw ModuleException("enc_old is deprecated and can not be used as a primary encryption method");

		ModuleManager::LoadModule("enc_md5", User::Find(creator));
		if (!md5)
			throw ModuleException("Unable to find md5 reference");

	}
Exemplo n.º 12
0
	ModuleChanFilter(InspIRCd* Me)
		: Module(Me)
	{
		cf = new ChanFilter(ServerInstance);
		if (!ServerInstance->AddMode(cf, 'g'))
			throw ModuleException("Could not add new modes!");
	}
Exemplo n.º 13
0
	ModuleDeaf(InspIRCd* Me)
		: Module(Me)
	{
		m1 = new User_d(ServerInstance);
		if (!ServerInstance->AddMode(m1, 'd'))
			throw ModuleException("Could not add new modes!");
	}
Exemplo n.º 14
0
	ModuleXMLRPCMain(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), xmlrpc("XMLRPCServiceInterface", "xmlrpc")
	{
		if (!xmlrpc)
			throw ModuleException("Unable to find xmlrpc reference, is m_xmlrpc loaded?");

		xmlrpc->Register(&stats);
	}
Exemplo n.º 15
0
	SSLModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
		, service(this, "ssl")
	{
		me = this;

		this->SetPermanent(true);

		SSL_library_init();
		SSL_load_error_strings();

		client_ctx = SSL_CTX_new(SSLv23_client_method());
		server_ctx = SSL_CTX_new(SSLv23_server_method());

		if (!client_ctx || !server_ctx)
			throw ModuleException("Error initializing SSL CTX");

		long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE;
		SSL_CTX_set_options(client_ctx, opts);
		SSL_CTX_set_options(server_ctx, opts);

		SSL_CTX_set_mode(client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
		SSL_CTX_set_mode(server_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

		Anope::string context_name = "Anope";
		SSL_CTX_set_session_id_context(client_ctx, reinterpret_cast<const unsigned char *>(context_name.c_str()), context_name.length());
		SSL_CTX_set_session_id_context(server_ctx, reinterpret_cast<const unsigned char *>(context_name.c_str()), context_name.length());
	}
Exemplo n.º 16
0
void ModuleManager::RequireVersion(int major, int minor, int patch, int build)
{
	if (Anope::VersionMajor() > major)
		return;
	else if (Anope::VersionMajor() == major)
	{
		if (minor == -1)
			return;
		else if (Anope::VersionMinor() > minor)
			return;
		else if (Anope::VersionMinor() == minor)
		{
			if (patch == -1)
				return;
			else if (Anope::VersionPatch() > patch)
				return;
			else if (Anope::VersionPatch() == patch)
			{
				if (build == -1)
					return;
				else if (Anope::VersionBuild() >= build)
					return;
			}
		}
	}

	throw ModuleException("This module requires version " + stringify(major) + "." + stringify(minor) + "." + stringify(patch) + "-" + build + " - this is " + Anope::Version());
}
Exemplo n.º 17
0
	ModuleMsgFlood(InspIRCd* Me)
		: Module(Me)
	{
		
		mf = new MsgFlood(ServerInstance);
		if (!ServerInstance->AddMode(mf, 'f'))
			throw ModuleException("Could not add new modes!");
	}
Exemplo n.º 18
0
	ModuleKickNoRejoin(InspIRCd* Me)
		: Module(Me)
	{
		
		kr = new KickRejoin(ServerInstance);
		if (!ServerInstance->AddMode(kr, 'J'))
			throw ModuleException("Could not add new modes!");
	}
Exemplo n.º 19
0
	FilterResult(dynamic_reference<RegexFactory>& RegexEngine, const std::string& free, const std::string& rea, FilterAction act, long gt, const std::string& fla)
		: freeform(free), reason(rea), action(act), gline_time(gt)
	{
		if (!RegexEngine)
			throw ModuleException("Regex module implementing '"+RegexEngine.GetProvider()+"' is not loaded!");
		regex = RegexEngine->Create(free);
		this->FillFlags(fla);
	}
Exemplo n.º 20
0
	SQLiteListener(ModuleSQLite3* P, InspIRCd* Instance, int port, const std::string &addr) : ListenSocketBase(Instance, port, addr), Parent(P)
	{
		uslen = sizeof(sock_us);
		if (getsockname(this->fd,(sockaddr*)&sock_us,&uslen))
		{
			throw ModuleException("Could not getsockname() to find out port number for ITC port");
		}
	}
Exemplo n.º 21
0
	MSSendAll(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
		commandmssendall(this)
	{
		this->SetAuthor("Anope");

		if (!memoserv)
			throw ModuleException("No MemoServ!");
	}
Exemplo n.º 22
0
	ModuleAllowInvite(InspIRCd* Me) : Module(Me)
	{
		ni = new AllowInvite(ServerInstance);
		if (!ServerInstance->Modes->AddMode(ni))
			throw ModuleException("Could not add new modes!");
		Implementation eventlist[] = { I_OnUserPreInvite, I_On005Numeric };
		ServerInstance->Modules->Attach(eventlist, this, 2);
	}
Exemplo n.º 23
0
	ModuleAuditorium(InspIRCd* Me)
		: Module(Me)
	{
		aum = new AuditoriumMode(ServerInstance);
		if (!ServerInstance->AddMode(aum, 'u'))
			throw ModuleException("Could not add new modes!");
		OnRehash(NULL, "");
	}
Exemplo n.º 24
0
	NSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
		, commandnsgroup(this)
		, commandnsungroup(this)
		, commandnsglist(this)
	{
		if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
			throw ModuleException(modname + " can not be used with options:nonicknameownership enabled");
	}
Exemplo n.º 25
0
/** High level abstraction of dns used by application at large */
Resolver::Resolver(const std::string &source, QueryType qt, bool &cached, Module* creator) : Creator(creator), input(source), querytype(qt)
{
	ServerInstance->Logs->Log("RESOLVER",DEBUG,"Resolver::Resolver");
	cached = false;

	CQ = ServerInstance->Res->GetCache(source);
	if (CQ)
	{
		time_left = CQ->CalcTTLRemaining();
		if (!time_left)
		{
			ServerInstance->Res->DelCache(source);
		}
		else
		{
			cached = true;
			return;
		}
	}

	switch (querytype)
	{
		case DNS_QUERY_A:
			this->myid = ServerInstance->Res->GetIP(source.c_str());
		break;

		case DNS_QUERY_PTR4:
			querytype = DNS_QUERY_PTR;
			this->myid = ServerInstance->Res->GetNameForce(source.c_str(), PROTOCOL_IPV4);
		break;

		case DNS_QUERY_PTR6:
			querytype = DNS_QUERY_PTR;
			this->myid = ServerInstance->Res->GetNameForce(source.c_str(), PROTOCOL_IPV6);
		break;

		case DNS_QUERY_AAAA:
			this->myid = ServerInstance->Res->GetIP6(source.c_str());
		break;

		case DNS_QUERY_CNAME:
			this->myid = ServerInstance->Res->GetCName(source.c_str());
		break;

		default:
			ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS request with unknown query type %d", querytype);
			this->myid = -1;
		break;
	}
	if (this->myid == -1)
	{
		throw ModuleException("Resolver: Couldn't get an id to make a request");
	}
	else
	{
		ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS request id %d", this->myid);
	}
}
Exemplo n.º 26
0
	ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR)
		, ircd_proto(this)
		, message_away(this)
		, message_capab(this)
		, message_error(this)
		, message_invite(this)
		, message_kick(this)
		, message_kill(this)
		, message_mode(this)
		, message_motd(this)
		, message_notice(this)
		, message_part(this)
		, message_ping(this)
		, message_privmsg(this)
		, message_quit(this)
		, message_squit(this)
		, message_stats(this)
		, message_time(this)
		, message_topic(this)
		, message_version(this)
		, message_whois(this)

		, message_bmask("IRCDMessage", "plexus/bmask", "hybrid/bmask")
		, message_eob("IRCDMessage", "plexus/eob", "hybrid/eob")
		, message_join("IRCDMessage", "plexus/join", "hybrid/join")
		, message_nick("IRCDMessage", "plexus/nick", "hybrid/nick")
		, message_sid("IRCDMessage", "plexus/sid", "hybrid/sid")
		, message_sjoin("IRCDMessage", "plexus/sjoin", "hybrid/sjoin")
		, message_tburst("IRCDMessage", "plexus/tburst", "hybrid/tburst")
		, message_tmode("IRCDMessage", "plexus/tmode", "hybrid/tmode")

		, message_encap(this)
		, message_pass(this)
		, message_server(this)
		, message_uid(this)
	{

		if (ModuleManager::LoadModule("hybrid", User::Find(creator)) != MOD_ERR_OK)
			throw ModuleException("Unable to load hybrid");
		m_hybrid = ModuleManager::FindModule("hybrid");
		if (!m_hybrid)
			throw ModuleException("Unable to find hybrid");
//		if (!hybrid)
//			throw ModuleException("No protocol interface for hybrid");
	}
Exemplo n.º 27
0
	LogChan(const Flux::string &Name): Module(Name)
	{
		this->SetVersion(VERSION);
		this->SetAuthor("Justasic");
		ModuleHandler::Attach(I_OnLog, this);

		if(Config->LogChan.empty())
			throw ModuleException("Log channel is empty, cannot load m_logchan!");
	}
Exemplo n.º 28
0
    ModuleXMLRPCMain(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
    {
        me = this;

        if (!xmlrpc)
            throw ModuleException("Unable to find xmlrpc reference, is m_xmlrpc loaded?");

        xmlrpc->Register(&stats);
    }
Exemplo n.º 29
0
 ModuleHideIdle(InspIRCd* Me)
         : Module::Module(Me)
 {
         mode = new ModeHideIdle(ServerInstance);
         if (!ServerInstance->Modes->AddMode(mode))
                 throw ModuleException("Could not add new modes!");
         Implementation eventlist[] = { I_OnWhoisLine };
         ServerInstance->Modules->Attach(eventlist, this, 1);
 }
Exemplo n.º 30
0
	HSRequest(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
		, commandhsrequest(this)
		, commandhsactive(this)
		, commandhsreject(this)
		, commandhswaiting(this)
		, hrtype(this)
	{
		if (!IRCD || !IRCD->CanSetVHost)
			throw ModuleException("Your IRCd does not support vhosts");
	}