Beispiel #1
0
/**
 * \fn void ModuleHandler::SanitizeRuntime()
 * \brief Deletes all files in the runtime directory.
 */
void ModuleHandler::SanitizeRuntime()
{
	Log(LOG_DEBUG) << "Cleaning up runtime directory.";
	Flux::string dirbuf = binary_dir + "/runtime/";

	if(!TextFile::IsDirectory(dirbuf))
	{
#ifndef _WIN32

		if(mkdir(dirbuf.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
			throw CoreException(printfify("Error making new runtime directory: %s", strerror(errno)));

#else

		if(!CreateDirectory(dirbuf.c_str(), NULL))
			throw CoreException(printfify("Error making runtime new directory: %s", strerror(errno)));

#endif
	}
	else
	{
		Flux::vector files = TextFile::DirectoryListing(dirbuf);

		for(Flux::vector::iterator it = files.begin(); it != files.end(); ++it)
			Delete(Flux::string(dirbuf + (*it)).c_str());
	}
}
Beispiel #2
0
	void Run(CommandSource &source, const Flux::vector &params)
	{
		Flux::string chan = params[1];
		User *u = source.u;

		if(!u->IsOwner())
		{
			source.Reply(ACCESS_DENIED);
			Log(u) << "attempted to make bot part " << chan;
			return;
		}

		if(!IsValidChannel(chan))
			source.Reply(CHANNEL_X_INVALID, chan.c_str());
		else
		{
			Channel *c = findchannel(chan);

			if(c)
				c->SendPart();
			else
				source.Reply("I am not in channel \2%s\2", chan.c_str());

			Log(u) << "made the bot part " << chan;
		}
	}
Beispiel #3
0
/** The equivalent of inet_pton
 * @param type AF_INET or AF_INET6
 * @param address The address to place in the sockaddr structures
 * @param pport An option port to include in the  sockaddr structures
 * @throws A socket exception if given invalid IPs
 */
void sockaddrs::pton(int type, const Flux::string &address, int pport)
{
	switch (type)
	{
		case AF_INET:
			int i = inet_pton(type, address.c_str(), &sa4.sin_addr);
			if (i == 0)
				throw SocketException("Invalid host");
			else if (i <= -1)
				throw SocketException(printfify("Invalid host: %s", strerror(errno)));
			sa4.sin_family = type;
			sa4.sin_port = htons(pport);
			return;
		case AF_INET6:
			int i = inet_pton(type, address.c_str(), &sa6.sin6_addr);
			if (i == 0)
				throw SocketException("Invalid host");
			else if (i <= -1)
				throw SocketException(printfify("Invalid host: %s", strerror(errno)));
			sa6.sin6_family = type;
			sa6.sin6_port = htons(pport);
			return;
		default:
			break;
	}

	throw CoreException("Invalid socket type");
}
Beispiel #4
0
	void OnChannelOp(User *u, Channel *c, const Flux::string &mode, const Flux::string &nick)
	{
		if(!u || !c)
			return;

		if(c->name != Config->LogChannel)
			return;

		CLog("*** %s sets mode %s %s %s", u->nick.c_str(), c->name.c_str(), mode.c_str(), nick.c_str());
	}
Beispiel #5
0
/**
 * \fn bool ModuleHandler::DeleteModule(Module *m)
 * \brief Delete the Module from Module lists and unload it from navn completely
 * \param Module the Module to be removed
 */
bool ModuleHandler::DeleteModule(Module *m)
{
	SET_SEGV_LOCATION();

	if(!m || !m->handle)
		return false;

	void *handle = m->handle;
	Flux::string filepath = m->filepath;

	dlerror();
	void (*df)(Module *) = function_cast<void ( *)(Module *)>(dlsym(m->handle, "ModunInit"));
	const char *err = dlerror();

	if(!df && err && *err)
	{
		Log(LOG_WARN) << "No destroy function found for " << m->name << ", chancing delete...";
		delete m; /* we just have to chance they haven't overwrote the delete operator then... */
	}
	else
		df(m); /* Let the Module delete it self, just in case */


	if(handle)
		if(dlclose(handle))
			Log() << "[" << m->name << ".so] " << dlerror();

	if(!filepath.empty())
		Delete(filepath.c_str());

	return true;
}
Beispiel #6
0
/**
 * \fn void CheckLogDelete(Log *log)
 * \brief Check to see if logs need to be removed due to old age
 * \param log A log class variable
 */
void CheckLogDelete(Log *log)
{
	Flux::string dir = binary_dir + "/logs/";

	if(!TextFile::IsDirectory(dir))
	{
		Log(LOG_TERMINAL) << "Directory " << dir << " does not exist, making new directory.";
#ifndef _WIN32

		if(mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
			throw LogException("Failed to create directory " + dir + ": " + Flux::string(strerror(errno)));

#else

		if(!CreateDirectory(dir.c_str(), NULL))
			throw LogException("Failed to create directory " + dir + ": " + Flux::string(strerror(errno)));

#endif

	}

	Flux::vector files = TextFile::DirectoryListing(dir);

	if(log)
		files.push_back(log->filename);

	if(files.empty())
		Log(LOG_TERMINAL) << "No Logs!";

	for(Flux::vector::iterator it = files.begin(); it != files.end(); ++it)
	{
		Flux::string file = dir + (*it);

		if(TextFile::IsFile(file))
		{
			Flux::string t = file.isolate('-', ' ').strip('-');
			int timestamp = static_cast<int>(t);

			if(timestamp > (time(NULL) - 86400 * Config->LogAge) && timestamp != starttime)
			{
				Delete(file.c_str());
				Log(LOG_DEBUG) << "Deleted old logfile " << file;
			}
		}
	}
}
Beispiel #7
0
	void OnPart(User *u, Channel *c, const Flux::string &reason)
	{
		if(!u || !c)
			return;

		if(c->name != Config->LogChannel)
			return;

		CLog("*** %s has parted %s (%s)", u->nick.c_str(), c->name.c_str(), reason.c_str());
	}
Beispiel #8
0
int uname(struct utsname *info)
{
	// get the system information.
	OSVERSIONINFOEX wininfo;
	SYSTEM_INFO si;
	Flux::string WindowsVer = GetWindowsVersion();
	Flux::string cputype;
	char hostname[256] = "\0";
	ZeroMemory(&wininfo, sizeof(OSVERSIONINFOEX));
	ZeroMemory(&si, sizeof(SYSTEM_INFO));
	wininfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

	if(!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&wininfo)))
		return -1;

	GetSystemInfo(&si);

	// Get the hostname
	if(gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR)
		return -1;

	if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
		cputype = "64-bit";
	else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
		cputype = "32-bit";
	else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
		cputype = "Itanium 64-bit";

	// Fill the utsname struct with the windows system info
	strcpy(info->sysname, "Windows");
	strcpy(info->nodename, hostname);
	strcpy(info->release, WindowsVer.c_str());
	strcpy(info->version, printfify("%ld.%ld-%ld", wininfo.dwMajorVersion, wininfo.dwMinorVersion, wininfo.dwBuildNumber).c_str());
	strcpy(info->machine, cputype.c_str());

	// Null-Terminate
	info->nodename[strlen(info->nodename) - 1] = '\0';
	info->sysname[strlen(info->sysname) - 1] = '\0';
	info->release[strlen(info->sysname) - 1] = '\0';
	info->version[strlen(info->version) - 1] = '\0';
	info->machine[strlen(info->machine) - 1] = '\0';
}
Beispiel #9
0
 void Brain(User *u, Flux::string q)
 {
   if(!(cdt.requested >= 30))
   {
     cdt.requested++;
     Log(LOG_TERMINAL) << "Requests: " << cdt.requested;
     Sanitize(q);
     Flux::string str = "python brain.py "+q;
     Flux::string information = execute(str.c_str());
     information.trim();
     if (information.search_ci("For search options, see Help:Searching")) u->SendMessage(RandomOops());
     else if (information.search_ci("may refer to:") ||  information.search_ci("reasons this message may be displayed:") ) u->SendMessage(RandomAmb());
     else u->SendMessage(information.strip());
   }else
     u->SendMessage(TooManyRequests());
 }
Beispiel #10
0
Flux::string ForwardResolution(const Flux::string &hostname)
{
  struct addrinfo *result, *res;
  int err = getaddrinfo(hostname.c_str(), NULL, NULL, &result);
  
  if(err != 0)
  {
    Log(LOG_TERMINAL) << "Failed to resolve " << hostname << ": " << gai_strerror(err);
    return "";
  }
  
  bool gothost = false;
  Flux::string ret = hostname;
  for(res = result; res != NULL && !gothost; res = res->ai_next)
  {
    struct sockaddr *haddr;
    haddr = res->ai_addr;
    char address[INET6_ADDRSTRLEN + 1] = "\0";
    switch(haddr->sa_family)
    {
      case AF_INET:
	struct sockaddr_in *v4;
	v4 = reinterpret_cast<struct sockaddr_in*>(haddr);
	if (!inet_ntop(AF_INET, &v4->sin_addr, address, sizeof(address)))
	{
	  Log(LOG_DEBUG) << "DNS: " << strerror(errno);
	  return "";
	}
	break;
      case AF_INET6:
	struct sockaddr_in6 *v6;
	v6 = reinterpret_cast<struct sockaddr_in6*>(haddr);
	if (!inet_ntop(AF_INET6, &v6->sin6_addr, address, sizeof(address)))
	{
	  Log(LOG_DEBUG) << "DNS: " << strerror(errno);
	  return "";
	}
	break;
    }
    
    ret = address;
    gothost = true;
  }
  
  freeaddrinfo(result);
  return ret;
}
Beispiel #11
0
  void Run(CommandSource &source, const Flux::vector &params)
  {
    User *u = source.u;
    Channel *c = source.c;
    Flux::string area = params[0], tmpfile = TextFile::TempFile(binary_dir+"/runtime/navn_xml.tmp.XXXXXX");

    if(tmpfile.empty())
    {
      Log() << "Failed to get temp file";
      return;
    }
    area.trim();

    Flux::string url = Config->Parser->Get("Modules", "WeatherURL", "http://www.google.com/ig/api?weather=%l");
    url = url.replace_all_cs("%l", area.is_number_only()?area:area.url_str());

    Log(LOG_DEBUG) << "wget weather url \"" << url << "\" for !weather command used";
    system(Flux::string("wget -q -O "+tmpfile+" - "+url).c_str());
    XMLFile *xf = new XMLFile(tmpfile);

    Flux::string city = xf->Tags["xml_api_reply"].Tags["weather"].Tags["forecast_information"].Tags["city"].Attributes["data"].Value;
    Flux::string condition = xf->Tags["xml_api_reply"].Tags["weather"].Tags["current_conditions"].Tags["condition"].Attributes["data"].Value;
    Flux::string temp_f = xf->Tags["xml_api_reply"].Tags["weather"].Tags["current_conditions"].Tags["temp_f"].Attributes["data"].Value;
    Flux::string temp_c = xf->Tags["xml_api_reply"].Tags["weather"].Tags["current_conditions"].Tags["temp_c"].Attributes["data"].Value;
    Flux::string humidity = xf->Tags["xml_api_reply"].Tags["weather"].Tags["current_conditions"].Tags["humidity"].Attributes["data"].Value;
    Flux::string windy = xf->Tags["xml_api_reply"].Tags["weather"].Tags["current_conditions"].Tags["wind_condition"].Attributes["data"].Value;

    delete xf;

    if(city.strip().empty())
    {
      source.Reply("Weather information for \2%s\2 not found.", area.c_str());
      return;
    }
    int temp_k = static_cast<int>(temp_c) + 273; // Calculate degrees kelvin from degrees celsius
    c->SendMessage("%s Current Condition: %s, %s, %s, %s %cF %s %cC %iK", city.strip().c_str(), condition.strip().c_str(), humidity.strip().c_str(), windy.strip().c_str(), temp_f.c_str(), 0x00B0, temp_c.c_str(), 0x00B0, temp_k);

    Log(u, this) << "to get weather for area '" << area << "'";
  }
Beispiel #12
0
	void OnPrivmsgChannel(User *u, Channel *c, const Flux::vector &params)
	{
		Flux::string nolog = params.size() == 2 ? params[1] : "";

		if(!u || !c)
			return;

		if(c->name != Config->LogChannel)
			return;

		Flux::string msg = ConcatinateVector(params);

		if(nolog != "#nl" && u)
		{
			if(nolog == "\001ACTION")
			{
				msg = msg.erase(0, 8);
				CLog("*** %s %s", u->nick.c_str(), Flux::Sanitize(msg).c_str());
			}
			else
				CLog("<%s> %s", u->nick.c_str(), msg.c_str());
		}
	}
Beispiel #13
0
	void Run(CommandSource &source, const Flux::vector &params)
	{
		User *u = source.u;
		Flux::string chan = params[1];

		if(!u->IsOwner())
		{
			source.Reply(ACCESS_DENIED);
			Log(u) << "attempted to make the bot join " << chan;
			return;
		}

		if(!IsValidChannel(chan))
			source.Reply(CHANNEL_X_INVALID, chan.c_str());
		else
		{
			Log(u) << "made the bot join " << chan;
			Channel *c = findchannel(chan);

			if(!c)
			{
				ircproto->join(chan);

				Flux::string WelcomeMessage = Config->WelcomeMessage.replace_all_ci("{botnick}", Config->BotNick);
				WelcomeMessage.trim();

				if(!WelcomeMessage.empty())
					ircproto->privmsg(chan, WelcomeMessage);
			}
			else
			{
				Log(u) << "tried to make bot join " << c->name << " but we're already in that channel";
				source.Reply("Already in \2%s\2", c->name.c_str());
			}
		}
	}
Beispiel #14
0
int SocketIO::Send(Socket *s, const Flux::string &buf)
{
	return this->Send(s, buf.c_str(), buf.length());
}
Beispiel #15
0
	void OnQuit(User *u, const Flux::string &reason)
	{
		CLog("*** %s has quit (%s)", u->nick.c_str(), reason.c_str());
	}
Beispiel #16
0
void SocketIO::Process()
{
  SET_SEGV_LOCATION();
  timeval timeout;
  timeout.tv_sec = Config->SockWait;
  timeout.tv_usec = 0; //this timeout keeps the bot from being a CPU hog for no reason :)
  fd_set read = ReadFD, write = WriteFD, except = ExceptFD;

  FD_ZERO(&read);
  FD_SET(this->GetFD(), &read);

  int sres = select(this->GetFD() + 1, &read, &write, &except, &timeout);
  if(sres == -1 && errno != EINTR)
  {
    Log(LOG_DEBUG) << "Select() error: " << strerror(errno);
    return;
  }

  if(throwex) //throw a socket exception if we want to. mainly used for ping timeouts.
    throw SocketException(throwmsg);

  bool has_read = FD_ISSET(this->GetFD(), &read);
  bool has_write = FD_ISSET(this->GetFD(), &write);
  bool has_error = FD_ISSET(this->GetFD(), &except);

  if(has_error)
  {
    int optval = 0;
    socklen_t optlen = sizeof(optval);
    getsockopt(this->GetFD(), SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&optval), &optlen);
    errno = optval;
    FOREACH_MOD(I_OnSocketError, OnSocketError(optval ? strerror(errno) : "Unknown socket error"));
    throw SocketException("Socket error");
  }
  
  if(has_read)
  {
    char tbuf[BUFSIZE + 1] = "\0";
    size_t i = recv(this->GetFD(), tbuf, BUFSIZE, 0);
    
    if(i <= 0)
      throw SocketException(printfify("Socket Error: %s", strerror(errno)));
    
    sepstream sep(tbuf, '\n');
    Flux::string buf;
    while(sep.GetToken(buf))
    {
      this->LastBuf.clear();
      this->LastBuf = buf;
      if(!this->Read(buf))
	throw SocketException("Error reading socket");
    }

    FD_CLR(this->GetFD(), &ReadFD);
  }

  if(has_write)
  {
    Flux::string buf;
    while(!this->WriteBuffer.empty())
    {
      buf = this->WriteBuffer.front();
      this->WriteBuffer.pop();

      int i = ::send(this->GetFD(), buf.c_str(), buf.size(), MSG_NOSIGNAL);

      if(i <= -1 && !quitting)
	throw SocketException(printfify("Error writing \"%s\" to socket: %s", buf.c_str(), strerror(errno)));

      Log(LOG_RAWIO) << "Sent: " << buf << " | " << buf.size() << " bytes";
      
      this->LastBuf.clear();
      this->LastBuf = buf;

      buf.clear();
    }

    FD_CLR(this->GetFD(), &WriteFD);
  }
}
Beispiel #17
0
/**
 * \fn ModErr ModuleHandler::LoadModule(const Flux::string &modname)
 * \brief Load a Module into the bot
 * \param Module the Module to load
 */
ModErr ModuleHandler::LoadModule(const Flux::string &modname)
{
	SET_SEGV_LOCATION();

	if(modname.empty())
		return MOD_ERR_PARAMS;

	if(FindModule(modname))
		return MOD_ERR_EXISTS;

	Log() << "Attempting to load Module [" << modname << ']';

	Flux::string mdir = binary_dir + "/runtime/" + (modname.search(".so") ? modname + ".XXXXXX" : modname + ".so.XXXXXX");
	Flux::string input = Flux::string(binary_dir + "/" + (Config->ModuleDir.empty() ? modname : Config->ModuleDir + "/" + modname) + ".so").replace_all_cs("//", "/");

	TextFile mod(input);
	Flux::string output = TextFile::TempFile(mdir);
	Log(LOG_RAWIO) << "Runtime Module location: " << output;
	mod.Copy(output);

	if(mod.GetLastError() != FILE_IO_OK)
	{
		Log(LOG_RAWIO) << "Runtime Copy Error: " << mod.DecodeLastError();
		return MOD_ERR_FILE_IO;
	}

	dlerror();

	// FIXME: Somehow the binary_dir variable is lost when this executes >:|
	void *handle = dlopen(output.c_str(), RTLD_LAZY | RTLD_LOCAL);
	const char *err = dlerror();

	if(!handle && err && *err)
	{
		Log() << '[' << modname << "] " << err;
		return MOD_ERR_NOLOAD;
	}

	dlerror();
	Module *(*f)(const Flux::string &) = function_cast<Module * ( *)(const Flux::string &)>(dlsym(handle, "ModInit"));
	err = dlerror();

	if(!f && err && *err)
	{
		Log() << "No Module init function, moving on.";
		dlclose(handle);
		return MOD_ERR_NOLOAD;
	}

	if(!f)
		throw CoreException("Can't find Module constructor, yet no moderr?");

	Module *m;

	try
	{
		m = f(modname);
	}
	catch(const ModuleException &e)
	{
		Log() << "Error while loading " << modname << ": " << e.GetReason();
		return MOD_ERR_EXCEPTION;
	}

	m->filepath = output;
	m->filename = (modname.search(".so") ? modname : modname + ".so");
	m->handle = handle;

	FOREACH_MOD(OnModuleLoad, m);

	return MOD_ERR_OK;
}