CmdResult Handle(const std::vector<std::string> ¶meters, User *user) { if(user->registered == REG_ALL) return CMD_FAILURE; for(CGIHostlist::iterator iter = Hosts.begin(); iter != Hosts.end(); iter++) { if(InspIRCd::Match(user->host, iter->hostmask, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(user->GetIPString(), iter->hostmask, ascii_case_insensitive_map)) { if(iter->type == WEBIRC && parameters[0] == iter->password) { realhost.set(user, user->host); realip.set(user, user->GetIPString()); bool host_ok = (parameters[2].length() < 64); const std::string& newhost = (host_ok ? parameters[2] : parameters[3]); if (notify) ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", user->nick.c_str(), user->host.c_str(), newhost.c_str(), user->host.c_str()); // Check if we're happy with the provided hostname. If it's problematic then make sure we won't set a host later, just the IP if (host_ok) webirc_hostname.set(user, parameters[2]); else webirc_hostname.unset(user); webirc_ip.set(user, parameters[3]); return CMD_SUCCESS; } } } ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s tried to use WEBIRC, but didn't match any configured webirc blocks.", user->GetFullRealHost().c_str()); return CMD_FAILURE; }
ModResult OnStats(char symbol, User* user, string_list &out) { if (symbol != 'G') return MOD_RES_PASSTHRU; unsigned int unknown = 0; std::map<std::string, unsigned int> results; for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); ++i) { std::string* cc = ext.get(*i); if (cc) results[*cc]++; else unknown++; } std::string p = ServerInstance->Config->ServerName + " 801 " + user->nick + " :GeoIPSTATS "; for (std::map<std::string, unsigned int>::const_iterator i = results.begin(); i != results.end(); ++i) { out.push_back(p + i->first + " " + ConvToStr(i->second)); } if (unknown) out.push_back(p + "Unknown " + ConvToStr(unknown)); return MOD_RES_DENY; }
void SetExt(LocalUser* user) { const char* c = GeoIP_country_code_by_addr(gi, user->GetIPString().c_str()); if (!c) c = "UNK"; std::string* cc = new std::string(c); ext.set(user, cc); }
ModResult OnUserRegister(LocalUser* user) { std::string pingrpl = ServerInstance->GenRandomStr(10); user->Write("PING :%s", pingrpl.c_str()); if(sendsnotice) user->WriteServ("NOTICE %s :*** If you are having problems connecting due to ping timeouts, please type /quote PONG %s or /raw PONG %s now.", user->nick.c_str(), pingrpl.c_str(), pingrpl.c_str()); ext.set(user, pingrpl); return MOD_RES_PASSTHRU; }
ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser* user, bool validated, const std::string &original_line) { if (command == "PONG") { std::string* pingrpl = ext.get(user); if (pingrpl) { if (!parameters.empty() && *pingrpl == parameters[0]) { ext.unset(user); return MOD_RES_DENY; } else { if(killonbadreply) ServerInstance->Users->QuitUser(user, "Incorrect ping reply for registration"); return MOD_RES_DENY; } } } return MOD_RES_PASSTHRU; }
ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) { std::string* cc = ext.get(user); if (!cc) SetExt(user); std::string geoip = myclass->config->getString("geoip"); if (geoip.empty()) return MOD_RES_PASSTHRU; irc::commasepstream list(geoip); std::string country; while (list.GetToken(country)) if (country == *cc) return MOD_RES_PASSTHRU; return MOD_RES_DENY; }
void init() { gi = GeoIP_new(GEOIP_STANDARD); if (gi == NULL) throw ModuleException("Unable to initialize geoip, are you missing GeoIP.dat?"); ServerInstance->Modules->AddService(ext); Implementation eventlist[] = { I_OnSetConnectClass, I_OnStats }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); ++i) { LocalUser* user = *i; if ((user->registered == REG_ALL) && (!ext.get(user))) { SetExt(user); } } }
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { LocalUser* user = IS_LOCAL(dest); /* For remote clients, we don't take any action, we just allow it. * The local server where they are will set their cloak instead. * This is fine, as we will receive it later. */ if (!user) { dest->SetMode(this, adding); return MODEACTION_ALLOW; } if (user->uuid == debounce_uid && debounce_ts == ServerInstance->Time()) { // prevent spamming using /mode user +x-x+x-x+x-x if (++debounce_count > 2) return MODEACTION_DENY; } else { debounce_uid = user->uuid; debounce_count = 1; debounce_ts = ServerInstance->Time(); } if (adding == user->IsModeSet(this)) return MODEACTION_DENY; /* don't allow this user to spam modechanges */ if (source == dest) user->CommandFloodPenalty += 5000; if (adding) { std::string* cloak = ext.get(user); if (!cloak) { /* Force creation of missing cloak */ creator->OnUserConnect(user); cloak = ext.get(user); } if (cloak) { user->ChangeDisplayedHost(*cloak); user->SetMode(this, true); return MODEACTION_ALLOW; } else return MODEACTION_DENY; } else { /* User is removing the mode, so restore their real host * and make it match the displayed one. */ user->SetMode(this, false); user->ChangeDisplayedHost(user->host.c_str()); return MODEACTION_ALLOW; } }
ModResult OnCheckReady(LocalUser* user) { return ext.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU; }