mirror of
https://github.com/anope/anope.git
synced 2026-06-15 08:34:47 +02:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0574de2d22 | |||
| c9c53dbe61 | |||
| a084245822 | |||
| 77e3f062da | |||
| 8bb3067e42 | |||
| 0c469abe4a | |||
| d63e32a579 | |||
| f13c450b93 | |||
| e95c07291a | |||
| 2963fc0a1d | |||
| 5d309d46e1 | |||
| 2e7fcd3098 | |||
| 884759aed4 | |||
| 2ec65023a6 | |||
| 0093f3fa44 | |||
| 2ad76278dd | |||
| 23e59d9f2c | |||
| 3cb9e0b97c | |||
| 0b7b6d9d6d | |||
| 56e6efbe8f | |||
| feed624cdc | |||
| 1a6f42b994 | |||
| 04f49225c9 | |||
| b18d1a69b6 | |||
| 0ace685597 | |||
| bfcfd0b727 | |||
| 087f1cb359 | |||
| 010d20198e | |||
| 953e804231 | |||
| c656fe0694 | |||
| fb3ec7a897 | |||
| 274658f955 | |||
| 7621306f4b | |||
| b804867105 | |||
| f8f1550c31 | |||
| 0fcc66711b | |||
| 8d9574e306 | |||
| 6cb17c734c | |||
| 3545e8e383 | |||
| 3c18e02b0b | |||
| b831cd8a36 | |||
| 516ab164f6 | |||
| b2d028533d | |||
| a88d9cb1f0 | |||
| b57ef5d2c7 | |||
| 1a96390826 | |||
| 60339edf40 | |||
| 6990c692d6 | |||
| 98e62b4032 | |||
| a1d7d42d6a | |||
| 3f7c0829ef | |||
| 46d8af781d | |||
| 67b7c8bd7d | |||
| 21486e2c81 | |||
| 29ac40b584 | |||
| dde444ed0e | |||
| 9b6c209c80 | |||
| 3c7d67c8cd | |||
| c730291762 | |||
| c593661f40 | |||
| 3b62c8f3e2 |
@@ -0,0 +1,46 @@
|
||||
## About
|
||||
|
||||
Anope is an open source set of IRC Services. It is highly modular, with a vast number of configurable parameters, and is the most used IRC services package. There are also many modules on the [modsite](https://modules.anope.org) to add additional features. It runs on Linux, BSD, and Windows, and supports many modern IRCds, including InspIRCd, UnrealIRCd, and ircd-hybrid. For more details, credits, command line options, and contact information see [docs/README](https://github.com/anope/anope/blob/2.0/docs/README).
|
||||
|
||||
* [Website](https://anope.org)
|
||||
* [GitHub](https://github.com/anope)
|
||||
* IRC \#anope on irc.anope.org
|
||||
|
||||
## Installation
|
||||
|
||||
### Linux/BSD
|
||||
Download the latest release off of the [releases page](https://github.com/anope/anope/releases).
|
||||
|
||||
|
||||
```
|
||||
$ ./Config
|
||||
$ cd build
|
||||
$ make
|
||||
$ make install
|
||||
```
|
||||
|
||||
Now change to the directory where you installed Anope to, e.g. `$ cd ~/services/`
|
||||
|
||||
### Windows
|
||||
Download the latest release off of the [releases page](https://github.com/anope/anope/releases) and run the installer.
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
Copy conf/example.conf to conf/services.conf
|
||||
|
||||
```
|
||||
$ cp conf/example.conf conf/services.conf
|
||||
```
|
||||
|
||||
Edit services.conf, configuring the uplink, serverinfo, and protocol module configurations. Example link blocks for popular IRCds are included in the the example.conf documentation. The [Anope wiki](https://wiki.anope.org) is also a good source of information. Our support channel is located at #anope on [irc.anope.org](irc://irc.anope.org/#anope).
|
||||
|
||||
Note that the example configuration file includes other example configuration files. If you want to modify the other example configuration files, copy them (e.g. `modules.example.conf` to `modules.conf`) and modify the `include` directive in `services.conf` to include the new file.
|
||||
|
||||
## Running
|
||||
|
||||
Run `$ ./bin/services` to start Anope. If asked to provide logs for support, use the `--support` flag, e.g.: `$ ./bin/services --support`
|
||||
|
||||
## Installing extra modules
|
||||
|
||||
Extra modules, which are usually modules which require extra libraries to use, such as m\_mysql, can be enabled with the `./extras` command from the source directory. Then re-run `Config`, `make` and `make install` again. Third party modules can be installed by placing them into the `modules/third` directory.
|
||||
+8
-13
@@ -532,7 +532,7 @@ options
|
||||
*
|
||||
* Note for this to work the regex module providing the regex engine must be loaded.
|
||||
*/
|
||||
regexengine = "regex/pcre"
|
||||
#regexengine = "regex/pcre"
|
||||
|
||||
/*
|
||||
* A list of languages to load on startup that will be available in /nickserv set language.
|
||||
@@ -1201,23 +1201,14 @@ module
|
||||
* encrypted by this module. Old passwords stored in another encryption method are
|
||||
* automatically re-encrypted by the primary encryption module on next identify.
|
||||
*
|
||||
* NOTE: enc_old is Anope's previous (broken) MD5 implementation which is present in
|
||||
* versions prior to Anope 1.7.17. If your databases were made using that module,
|
||||
* use this and not enc_md5.
|
||||
*
|
||||
* NOTE: enc_sha1 relies on how the OS stores 2+ byte data internally, and is
|
||||
* potentially broken when moving between 2 different OSes, such as moving from
|
||||
* Linux to Windows. It is recommended that you use enc_sha256 instead if you want
|
||||
* to use an SHA-based encryption. If you choose to do so, it is also recommended
|
||||
* that you first try to get everyone's passwords converted to enc_sha256 before
|
||||
* switching OSes by placing enc_sha256 at the beginning of the list.
|
||||
* enc_md5, enc_sha1, and enc_old are deprecated, and are provided for users
|
||||
* to upgrade to a newer encryption module. Do not use them as the primary
|
||||
* encryption module. They will be removed in a future release.
|
||||
*
|
||||
*/
|
||||
|
||||
#module { name = "enc_bcrypt" }
|
||||
module { name = "enc_sha256" }
|
||||
#module { name = "enc_md5" }
|
||||
#module { name = "enc_sha1" }
|
||||
|
||||
/*
|
||||
* When using enc_none, passwords will be stored without encryption. This isn't secure
|
||||
@@ -1225,6 +1216,10 @@ module { name = "enc_sha256" }
|
||||
*/
|
||||
#module { name = "enc_none" }
|
||||
|
||||
/* Deprecated encryption modules */
|
||||
#module { name = "enc_md5" }
|
||||
#module { name = "enc_sha1" }
|
||||
|
||||
/*
|
||||
* enc_old is Anope's previous (broken) MD5 implementation used from 1.4.x to 1.7.16.
|
||||
* If your databases were made using that module, load it here to allow conversion to the primary
|
||||
|
||||
@@ -175,7 +175,7 @@ module { name = "help" }
|
||||
}
|
||||
|
||||
/* Exempt localhost from DNSBL checks */
|
||||
exempt { ip = "127.0.0.1" }
|
||||
exempt { ip = "127.0.0.0/8" }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -540,7 +540,7 @@ module { name = "help" }
|
||||
* authenticating users through this mechanism. Supported mechanisms are:
|
||||
* PLAIN, EXTERNAL.
|
||||
*/
|
||||
#module { name = "m_sasl" }
|
||||
module { name = "m_sasl" }
|
||||
|
||||
/*
|
||||
* m_ssl_gnutls [EXTRA]
|
||||
|
||||
@@ -106,7 +106,7 @@ module
|
||||
* - autoop: User will be automatically opped in channels they enter and have access to
|
||||
* - msg: Services messages will be sent as PRIVMSGs instead of NOTICEs, requires
|
||||
* options:useprivmsg to be enabled as well
|
||||
* - ns_keepmodes: Enables keepmodes, which retains user modes across sessions
|
||||
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
|
||||
* - ns_no_expire: Enables no expire. Unconfirmed expire overrules this.
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to ns_secure, memo_signon, and
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
Anope Version 2.0.6
|
||||
-------------------
|
||||
Log client IP for web clients running commands via webcpanel
|
||||
Fix log file path for the config file could not be opened log message
|
||||
Allow nickserv/group to be used via XMLRPC
|
||||
Fix logsearch without wildcards
|
||||
Support cidr exempts in m_dnsbl
|
||||
Add support for IPv6 dnsbls
|
||||
Add +u and +L channel modes for ircd-hybrid
|
||||
Set +x after hostserv/off on InspIRCd and UnrealIRCd
|
||||
Fix chanserv/mode not being able to set extbans
|
||||
Send CHGIDENT/CHGHOST on SVSLOGIN on InspIRCd
|
||||
Fix escaping replies from commands in webcpanel
|
||||
Enable require_oper for all opers added via operserv/oper
|
||||
Advertise SASL mechanisms to UnrealIRCd servers
|
||||
|
||||
Anope Version 2.0.5
|
||||
-------------------
|
||||
Fix negative levels to not match users with negative access
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
Anope Version 2.0.6
|
||||
-------------------
|
||||
Mark enc_md5 and enc_sha1 as deprecated. Their use has been discouraged for years, and they will be removed in a future release.
|
||||
Exempt all of 127.0.0.0/8 from m_dnsbl by default
|
||||
Load m_sasl by default
|
||||
Fix documentation for nickserv default option ns_keep_modes
|
||||
|
||||
Anope Version 2.0.5
|
||||
-------------------
|
||||
No significant changes.
|
||||
|
||||
+2
-4
@@ -9,8 +9,6 @@ This program is free but copyrighted software; see the file COPYING for
|
||||
details.
|
||||
|
||||
Information about Anope may be found at http://www.anope.org/
|
||||
Information about Epona may be found at http://www.epona.org/
|
||||
Information about Services may be found at http://www.ircservices.esper.net/
|
||||
|
||||
Table of Contents
|
||||
-----------------
|
||||
@@ -19,7 +17,7 @@ Table of Contents
|
||||
3) Installation
|
||||
4) Command Line Options
|
||||
5) Messages Translation
|
||||
6) Contact and Mailing List
|
||||
6) Contact
|
||||
|
||||
1) Credits
|
||||
|
||||
@@ -170,7 +168,7 @@ Table of Contents
|
||||
|
||||
* Bahamut 1.4.27 or later (including 1.8)
|
||||
* Charybdis 3.4 or later
|
||||
* Hybrid 8.1 or later
|
||||
* Hybrid 8.2 or later
|
||||
* InspIRCd 1.2 or 2.0
|
||||
* ngIRCd 19.2 or later
|
||||
* Plexus 3 or later
|
||||
|
||||
@@ -246,6 +246,7 @@ class CoreExport IdentifyRequest
|
||||
virtual void OnSuccess() = 0;
|
||||
virtual void OnFail() = 0;
|
||||
|
||||
Module *GetOwner() const { return owner; }
|
||||
const Anope::string &GetAccount() const { return account; }
|
||||
const Anope::string &GetPassword() const { return password; }
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ class CoreExport CommandSource
|
||||
public:
|
||||
/* The account executing the command */
|
||||
Reference<NickCore> nc;
|
||||
/* for web clients */
|
||||
Anope::string ip;
|
||||
/* Where the reply should go */
|
||||
CommandReply *reply;
|
||||
/* Channel the command was executed on (fantasy) */
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace Configuration
|
||||
File(const Anope::string &, bool);
|
||||
~File();
|
||||
const Anope::string &GetName() const;
|
||||
Anope::string GetPath() const;
|
||||
|
||||
bool IsOpen() const;
|
||||
bool Open();
|
||||
|
||||
@@ -301,6 +301,11 @@ class CoreExport Module : public Extensible
|
||||
* before they will be called.
|
||||
*/
|
||||
|
||||
/** Called on startup after database load, but before
|
||||
* connecting to the uplink.
|
||||
*/
|
||||
virtual void OnPostInit() { throw NotImplementedException(); }
|
||||
|
||||
/** Called before a user has been kicked from a channel.
|
||||
* @param source The kicker
|
||||
* @param cu The user, channel, and status of the user being kicked
|
||||
@@ -1099,6 +1104,7 @@ class CoreExport Module : public Extensible
|
||||
|
||||
enum Implementation
|
||||
{
|
||||
I_OnPostInit,
|
||||
I_OnPreUserKicked, I_OnUserKicked, I_OnReload, I_OnPreBotAssign, I_OnBotAssign, I_OnBotUnAssign, I_OnUserConnect,
|
||||
I_OnNewServer, I_OnUserNickChange, I_OnPreHelp, I_OnPostHelp, I_OnPreCommand, I_OnPostCommand, I_OnSaveDatabase,
|
||||
I_OnLoadDatabase, I_OnEncrypt, I_OnDecrypt, I_OnBotFantasy, I_OnBotNoFantasyAccess, I_OnBotBan, I_OnBadWordAdd,
|
||||
|
||||
@@ -228,6 +228,9 @@ namespace HTTPUtils
|
||||
case '"':
|
||||
dst += """;
|
||||
break;
|
||||
case '&':
|
||||
dst += "&";
|
||||
break;
|
||||
default:
|
||||
dst += src[i];
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ class ForbidService : public Service
|
||||
|
||||
virtual ForbidData *FindForbid(const Anope::string &mask, ForbidType type) = 0;
|
||||
|
||||
virtual ForbidData *FindForbidExact(const Anope::string &mask, ForbidType type) = 0;
|
||||
|
||||
virtual std::vector<ForbidData *> GetForbids() = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace Redis
|
||||
public:
|
||||
Provider(Module *c, const Anope::string &n) : Service(c, "Redis::Provider", n) { }
|
||||
|
||||
virtual bool IsSocketDead() = 0;
|
||||
|
||||
virtual void SendCommand(Interface *i, const std::vector<Anope::string> &cmds) = 0;
|
||||
virtual void SendCommand(Interface *i, const Anope::string &str) = 0;
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace SASL
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
user = hostname + " (" + ip + ")";
|
||||
|
||||
Log(Config->GetClient("NickServ"), "sasl") << user << " identified to account " << this->GetAccount() << " using SASL";
|
||||
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << user << " identified to account " << this->GetAccount() << " using SASL";
|
||||
sasl->Succeed(s, na->nc);
|
||||
delete s;
|
||||
}
|
||||
@@ -133,7 +133,7 @@ namespace SASL
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
user = hostname + " (" + ip + ")";
|
||||
|
||||
Log(Config->GetClient("NickServ"), "sasl") << user << " failed to identify for " << accountstatus << "account " << this->GetAccount() << " using SASL";
|
||||
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << user << " failed to identify for " << accountstatus << "account " << this->GetAccount() << " using SASL";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -57,6 +57,11 @@ union CoreExport sockaddrs
|
||||
*/
|
||||
Anope::string addr() const;
|
||||
|
||||
/** Get the reverse address represented by this addr
|
||||
* @return The reverse address
|
||||
*/
|
||||
Anope::string reverse() const;
|
||||
|
||||
/* Is this address ipv6? */
|
||||
bool ipv6() const;
|
||||
|
||||
|
||||
+275
-409
File diff suppressed because it is too large
Load Diff
+503
-602
File diff suppressed because it is too large
Load Diff
@@ -393,7 +393,7 @@ class CommandBSBadwords : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
if (!source.AccessFor(ci).HasPriv("BADWORDS") && (!need_args || !source.HasPriv("botserv/administration")))
|
||||
if (!source.AccessFor(ci).HasPriv("BADWORDS") && !source.HasPriv("botserv/administration"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
|
||||
@@ -13,6 +13,31 @@
|
||||
|
||||
class CommandCSAKick : public Command
|
||||
{
|
||||
void Enforce(CommandSource &source, ChannelInfo *ci)
|
||||
{
|
||||
Channel *c = ci->c;
|
||||
int count = 0;
|
||||
|
||||
if (!c)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; )
|
||||
{
|
||||
ChanUserContainer *uc = it->second;
|
||||
++it;
|
||||
|
||||
if (c->CheckKick(uc->user))
|
||||
++count;
|
||||
}
|
||||
|
||||
bool override = !source.AccessFor(ci).HasPriv("AKICK");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "ENFORCE, affects " << count << " users";
|
||||
|
||||
source.Reply(_("AKICK ENFORCE for \002%s\002 complete; \002%d\002 users were affected."), ci->name.c_str(), count);
|
||||
}
|
||||
|
||||
void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
Anope::string mask = params[2];
|
||||
@@ -164,7 +189,7 @@ class CommandCSAKick : public Command
|
||||
|
||||
source.Reply(_("\002%s\002 added to %s autokick list."), mask.c_str(), ci->name.c_str());
|
||||
|
||||
this->DoEnforce(source, ci);
|
||||
this->Enforce(source, ci);
|
||||
}
|
||||
|
||||
void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
@@ -384,7 +409,6 @@ class CommandCSAKick : public Command
|
||||
void DoEnforce(CommandSource &source, ChannelInfo *ci)
|
||||
{
|
||||
Channel *c = ci->c;
|
||||
int count = 0;
|
||||
|
||||
if (!c)
|
||||
{
|
||||
@@ -392,19 +416,7 @@ class CommandCSAKick : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; )
|
||||
{
|
||||
ChanUserContainer *uc = it->second;
|
||||
++it;
|
||||
|
||||
if (c->CheckKick(uc->user))
|
||||
++count;
|
||||
}
|
||||
|
||||
bool override = !source.AccessFor(ci).HasPriv("AKICK");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "ENFORCE, affects " << count << " users";
|
||||
|
||||
source.Reply(_("AKICK ENFORCE for \002%s\002 complete; \002%d\002 users were affected."), ci->name.c_str(), count);
|
||||
this->Enforce(source, ci);
|
||||
}
|
||||
|
||||
void DoClear(CommandSource &source, ChannelInfo *ci)
|
||||
|
||||
@@ -654,6 +654,10 @@ class CommandCSMode : public Command
|
||||
break;
|
||||
if (!sep.GetToken(param))
|
||||
break;
|
||||
|
||||
// Change to internal name, eg giving -b ~q:*
|
||||
cm = cm->Unwrap(param);
|
||||
|
||||
if (adding)
|
||||
{
|
||||
if (IRCD->GetMaxListFor(ci->c) && ci->c->HasMode(cm->name) < IRCD->GetMaxListFor(ci->c))
|
||||
@@ -667,10 +671,10 @@ class CommandCSMode : public Command
|
||||
ci->c->RemoveMode(NULL, cm, v[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to set " << params[2] << (params.size() > 3 ? " " + params[3] : "");
|
||||
} // switch
|
||||
}
|
||||
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to set " << modes << (params.size() > 3 ? " " + params[3] : "");
|
||||
}
|
||||
|
||||
void DoClear(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
@@ -709,6 +713,12 @@ class CommandCSMode : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cm->mchar)
|
||||
{
|
||||
source.Reply(_("Mode %s is a virtual mode and can't be cleared."), cm->name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Anope::string> new_params;
|
||||
new_params.push_back(params[0]);
|
||||
new_params.push_back("SET");
|
||||
|
||||
@@ -504,20 +504,6 @@ class CommandCSSetPersist : public Command
|
||||
{
|
||||
ci->Extend<bool>("PERSIST");
|
||||
|
||||
/* Channel doesn't exist, create it */
|
||||
if (!ci->c)
|
||||
{
|
||||
bool created;
|
||||
Channel *c = Channel::FindOrCreate(ci->name, created);
|
||||
if (ci->bi)
|
||||
{
|
||||
ChannelStatus status(BotModes());
|
||||
ci->bi->Join(c, &status);
|
||||
}
|
||||
if (created)
|
||||
c->Sync();
|
||||
}
|
||||
|
||||
/* Set the perm mode */
|
||||
if (cm)
|
||||
{
|
||||
@@ -541,7 +527,7 @@ class CommandCSSetPersist : public Command
|
||||
}
|
||||
|
||||
ChanServ->Assign(NULL, ci);
|
||||
if (!ci->c->FindUser(ChanServ))
|
||||
if (ci->c && !ci->c->FindUser(ChanServ))
|
||||
{
|
||||
ChannelStatus status(BotModes());
|
||||
ChanServ->Join(ci->c, &status);
|
||||
@@ -1099,7 +1085,8 @@ class CommandCSSetNoexpire : public Command
|
||||
class CSSet : public Module
|
||||
{
|
||||
SerializableExtensibleItem<bool> noautoop, peace, securefounder,
|
||||
restricted, secure, secureops, signkick, signkick_level, noexpire;
|
||||
restricted, secure, secureops, signkick, signkick_level, noexpire,
|
||||
persist;
|
||||
|
||||
struct KeepModes : SerializableExtensibleItem<bool>
|
||||
{
|
||||
@@ -1147,51 +1134,6 @@ class CSSet : public Module
|
||||
}
|
||||
} keep_modes;
|
||||
|
||||
struct Persist : SerializableExtensibleItem<bool>
|
||||
{
|
||||
Persist(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { }
|
||||
|
||||
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
|
||||
{
|
||||
SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data);
|
||||
|
||||
if (s->GetSerializableType()->GetName() != "ChannelInfo" || !this->HasExt(e))
|
||||
return;
|
||||
|
||||
ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(s);
|
||||
if (ci->c)
|
||||
return;
|
||||
|
||||
bool created;
|
||||
Channel *c = Channel::FindOrCreate(ci->name, created);
|
||||
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName("PERM");
|
||||
if (cm)
|
||||
{
|
||||
c->SetMode(NULL, cm);
|
||||
}
|
||||
/* on startup we might not know mode availibity here */
|
||||
else if (Me && Me->IsSynced())
|
||||
{
|
||||
if (!ci->bi)
|
||||
{
|
||||
BotInfo *ChanServ = Config->GetClient("ChanServ");
|
||||
if (ChanServ)
|
||||
ChanServ->Assign(NULL, ci);
|
||||
}
|
||||
|
||||
if (ci->bi && !c->FindUser(ci->bi))
|
||||
{
|
||||
ChannelStatus status(BotModes());
|
||||
ci->bi->Join(c, &status);
|
||||
}
|
||||
}
|
||||
|
||||
if (created)
|
||||
c->Sync();
|
||||
}
|
||||
} persist;
|
||||
|
||||
CommandCSSet commandcsset;
|
||||
CommandCSSetAutoOp commandcssetautoop;
|
||||
CommandCSSetBanType commandcssetbantype;
|
||||
@@ -1218,7 +1160,8 @@ class CSSet : public Module
|
||||
securefounder(this, "SECUREFOUNDER"), restricted(this, "RESTRICTED"),
|
||||
secure(this, "CS_SECURE"), secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"),
|
||||
signkick_level(this, "SIGNKICK_LEVEL"), noexpire(this, "CS_NO_EXPIRE"),
|
||||
keep_modes(this, "CS_KEEP_MODES"), persist(this, "PERSIST"),
|
||||
persist(this, "PERSIST"),
|
||||
keep_modes(this, "CS_KEEP_MODES"),
|
||||
|
||||
commandcsset(this), commandcssetautoop(this), commandcssetbantype(this),
|
||||
commandcssetdescription(this), commandcssetfounder(this), commandcssetkeepmodes(this),
|
||||
@@ -1299,7 +1242,7 @@ class CSSet : public Module
|
||||
|
||||
void OnJoinChannel(User *u, Channel *c) anope_override
|
||||
{
|
||||
if (persist_lower_ts && c->ci && persist.HasExt(c->ci) && c->creation_time > c->ci->time_registered)
|
||||
if (u->server != Me && persist_lower_ts && c->ci && persist.HasExt(c->ci) && c->creation_time > c->ci->time_registered)
|
||||
{
|
||||
Log(LOG_DEBUG) << "Changing TS of " << c->name << " from " << c->creation_time << " to " << c->ci->time_registered;
|
||||
c->creation_time = c->ci->time_registered;
|
||||
|
||||
@@ -156,6 +156,7 @@ class CommandCSSetMisc : public Command
|
||||
{
|
||||
if (descriptions.count(source.command))
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -561,7 +561,7 @@ class CommandCSXOP : public Command
|
||||
BotInfo *access_bi, *flags_bi;
|
||||
Anope::string access_cmd, flags_cmd;
|
||||
Command::FindCommandFromService("chanserv/access", access_bi, access_cmd);
|
||||
Command::FindCommandFromService("chanserv/flags", flags_bi, access_cmd);
|
||||
Command::FindCommandFromService("chanserv/flags", flags_bi, flags_cmd);
|
||||
if (!access_cmd.empty() || !flags_cmd.empty())
|
||||
{
|
||||
source.Reply(_("Alternative methods of modifying channel access lists are\n"
|
||||
|
||||
@@ -24,45 +24,58 @@ class NSGroupRequest : public IdentifyRequest
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!source.GetUser() || source.GetUser()->nick != nick || !target || !target->nc)
|
||||
User *u = source.GetUser();
|
||||
|
||||
/* user changed nick? */
|
||||
if (u != NULL && u->nick != nick)
|
||||
return;
|
||||
|
||||
if (!target || !target->nc)
|
||||
return;
|
||||
|
||||
User *u = source.GetUser();
|
||||
NickAlias *na = NickAlias::Find(nick);
|
||||
/* If the nick is already registered, drop it. */
|
||||
if (na)
|
||||
{
|
||||
FOREACH_MOD(OnChangeCoreDisplay, (na->nc, u->nick));
|
||||
delete na;
|
||||
}
|
||||
|
||||
na = new NickAlias(nick, target->nc);
|
||||
|
||||
Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
|
||||
na->last_usermask = last_usermask;
|
||||
na->last_realname = u->realname;
|
||||
na->time_registered = na->last_seen = Anope::CurTime;
|
||||
|
||||
u->Login(target->nc);
|
||||
FOREACH_MOD(OnNickGroup, (u, target));
|
||||
if (u != NULL)
|
||||
{
|
||||
na->last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
|
||||
na->last_realname = u->realname;
|
||||
}
|
||||
else
|
||||
{
|
||||
na->last_realname = source.GetNick();
|
||||
}
|
||||
|
||||
if (u != NULL)
|
||||
{
|
||||
u->Login(target->nc);
|
||||
FOREACH_MOD(OnNickGroup, (u, target));
|
||||
}
|
||||
|
||||
Log(LOG_COMMAND, source, cmd) << "to make " << nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")";
|
||||
source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str());
|
||||
|
||||
u->lastnickreg = Anope::CurTime;
|
||||
|
||||
if (u)
|
||||
u->lastnickreg = Anope::CurTime;
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (!source.GetUser())
|
||||
return;
|
||||
User *u = source.GetUser();
|
||||
|
||||
Log(LOG_COMMAND, source, cmd) << "and failed to group to " << target->nick;
|
||||
if (NickAlias::Find(GetAccount()) != NULL)
|
||||
{
|
||||
source.Reply(PASSWORD_INCORRECT);
|
||||
source.GetUser()->BadPassword();
|
||||
if (u)
|
||||
u->BadPassword();
|
||||
}
|
||||
else
|
||||
source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str());
|
||||
|
||||
@@ -153,6 +153,7 @@ class CommandNSSetMisc : public Command
|
||||
{
|
||||
if (descriptions.count(source.command))
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,18 @@ class MyForbidService : public ForbidService
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ForbidData *FindForbidExact(const Anope::string &mask, ForbidType ftype) anope_override
|
||||
{
|
||||
for (unsigned i = this->forbids(ftype).size(); i > 0; --i)
|
||||
{
|
||||
ForbidData *d = this->forbids(ftype)[i - 1];
|
||||
|
||||
if (d->mask.equals_ci(mask))
|
||||
return d;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::vector<ForbidData *> GetForbids() anope_override
|
||||
{
|
||||
std::vector<ForbidData *> f;
|
||||
@@ -203,7 +215,7 @@ class CommandOSForbid : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
ForbidData *d = this->fs->FindForbid(entry, ftype);
|
||||
ForbidData *d = this->fs->FindForbidExact(entry, ftype);
|
||||
bool created = false;
|
||||
if (d == NULL)
|
||||
{
|
||||
@@ -322,7 +334,7 @@ class CommandOSForbid : public Command
|
||||
{
|
||||
const Anope::string &entry = params[2];
|
||||
|
||||
ForbidData *d = this->fs->FindForbid(entry, ftype);
|
||||
ForbidData *d = this->fs->FindForbidExact(entry, ftype);
|
||||
if (d != NULL)
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
|
||||
@@ -113,7 +113,7 @@ class CommandOSLogSearch : public Command
|
||||
else if (wildcard)
|
||||
match = Anope::Match(buf, "*" + search_string + "*");
|
||||
else
|
||||
match = buf.find_first_of_ci(search_string) != Anope::string::npos;
|
||||
match = buf.find_ci(search_string) != Anope::string::npos;
|
||||
|
||||
if (match)
|
||||
{
|
||||
|
||||
@@ -109,7 +109,6 @@ class CommandOSOper : public Command
|
||||
}
|
||||
|
||||
na->nc->o = new MyOper(na->nc->display, ot);
|
||||
na->nc->o->require_oper = true;
|
||||
|
||||
if (Anope::ReadOnly)
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
|
||||
@@ -179,6 +179,12 @@ class DatabaseRedis : public Module, public Pipe
|
||||
|
||||
EventReturn OnLoadDatabase() anope_override
|
||||
{
|
||||
if (!redis)
|
||||
{
|
||||
Log(this) << "Unable to load database - unable to find redis provider";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
|
||||
for (unsigned i = 0; i < type_order.size(); ++i)
|
||||
{
|
||||
@@ -186,7 +192,13 @@ class DatabaseRedis : public Module, public Pipe
|
||||
this->OnSerializeTypeCreate(sb);
|
||||
}
|
||||
|
||||
while (redis->BlockAndProcess());
|
||||
while (!redis->IsSocketDead() && redis->BlockAndProcess());
|
||||
|
||||
if (redis->IsSocketDead())
|
||||
{
|
||||
Log(this) << "I/O error while loading redis database - is it online?";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
redis->Subscribe(&this->sl, "__keyspace@*__:hash:*");
|
||||
|
||||
@@ -215,6 +227,18 @@ class DatabaseRedis : public Module, public Pipe
|
||||
{
|
||||
Serialize::Type *t = obj->GetSerializableType();
|
||||
|
||||
if (t == NULL)
|
||||
{
|
||||
/* This is probably the module providing the type unloading.
|
||||
*
|
||||
* The types get registered after the extensible container is
|
||||
* registered so that unserialization on module load can insert
|
||||
* into the extensible container. So, the type destructs prior to
|
||||
* the extensible container, which then triggers this
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.push_back("HGETALL");
|
||||
args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
|
||||
|
||||
@@ -17,7 +17,7 @@ class POSIXRegex : public Regex
|
||||
public:
|
||||
POSIXRegex(const Anope::string &expr) : Regex(expr)
|
||||
{
|
||||
int err = regcomp(&this->regbuf, expr.c_str(), REG_EXTENDED | REG_NOSUB);
|
||||
int err = regcomp(&this->regbuf, expr.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE);
|
||||
if (err)
|
||||
{
|
||||
char buf[BUFSIZE];
|
||||
|
||||
+9
-25
@@ -296,32 +296,16 @@ class Packet : public Query
|
||||
if (!ip.valid())
|
||||
throw SocketException("Invalid IP");
|
||||
|
||||
if (q.name.find(':') != Anope::string::npos)
|
||||
switch (ip.family())
|
||||
{
|
||||
const char *const hex = "0123456789abcdef";
|
||||
char reverse_ip[128];
|
||||
unsigned reverse_ip_count = 0;
|
||||
for (int j = 15; j >= 0; --j)
|
||||
{
|
||||
reverse_ip[reverse_ip_count++] = hex[ip.sa6.sin6_addr.s6_addr[j] & 0xF];
|
||||
reverse_ip[reverse_ip_count++] = '.';
|
||||
reverse_ip[reverse_ip_count++] = hex[ip.sa6.sin6_addr.s6_addr[j] >> 4];
|
||||
reverse_ip[reverse_ip_count++] = '.';
|
||||
}
|
||||
reverse_ip[reverse_ip_count++] = 0;
|
||||
|
||||
q.name = reverse_ip;
|
||||
q.name += "ip6.arpa";
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long forward = ip.sa4.sin_addr.s_addr;
|
||||
in_addr reverse;
|
||||
reverse.s_addr = forward << 24 | (forward & 0xFF00) << 8 | (forward & 0xFF0000) >> 8 | forward >> 24;
|
||||
|
||||
ip.ntop(AF_INET, &reverse);
|
||||
|
||||
q.name = ip.addr() + ".in-addr.arpa";
|
||||
case AF_INET6:
|
||||
q.name = ip.reverse() + ".ip6.arpa";
|
||||
break;
|
||||
case AF_INET:
|
||||
q.name = ip.reverse() + ".in-addr.arpa";
|
||||
break;
|
||||
default:
|
||||
throw SocketException("Unsupported IP Family");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-11
@@ -99,7 +99,7 @@ class DNSBLResolver : public Request
|
||||
class ModuleDNSBL : public Module
|
||||
{
|
||||
std::vector<Blacklist> blacklists;
|
||||
std::set<Anope::string> exempts;
|
||||
std::set<cidr> exempts;
|
||||
bool check_on_connect;
|
||||
bool check_on_netburst;
|
||||
bool add_to_akill;
|
||||
@@ -146,7 +146,10 @@ class ModuleDNSBL : public Module
|
||||
|
||||
this->exempts.clear();
|
||||
for (int i = 0; i < block->CountBlock("exempt"); ++i)
|
||||
this->exempts.insert(block->Get<Anope::string>("ip"));
|
||||
{
|
||||
Configuration::Block *bl = block->GetBlock("exempt", i);
|
||||
this->exempts.insert(bl->Get<Anope::string>("ip"));
|
||||
}
|
||||
}
|
||||
|
||||
void OnUserConnect(User *user, bool &exempt) anope_override
|
||||
@@ -157,25 +160,26 @@ class ModuleDNSBL : public Module
|
||||
if (!this->check_on_netburst && !user->server->IsSynced())
|
||||
return;
|
||||
|
||||
/* At this time we only support IPv4 */
|
||||
if (!user->ip.valid() || user->ip.sa.sa_family != AF_INET)
|
||||
/* User doesn't have a valid IPv4 IP (ipv6/spoof/etc) */
|
||||
if (!user->ip.valid())
|
||||
/* User doesn't have a valid IP (spoof/etc) */
|
||||
return;
|
||||
|
||||
if (this->blacklists.empty())
|
||||
return;
|
||||
|
||||
if (this->exempts.count(user->ip.addr()))
|
||||
{
|
||||
Log(LOG_DEBUG) << "User " << user->nick << " is exempt from dnsbl check - ip: " << user->ip.addr();
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned long &ip = user->ip.sa4.sin_addr.s_addr;
|
||||
unsigned long reverse_ip = (ip << 24) | ((ip & 0xFF00) << 8) | ((ip & 0xFF0000) >> 8) | (ip >> 24);
|
||||
|
||||
sockaddrs reverse = user->ip;
|
||||
reverse.sa4.sin_addr.s_addr = reverse_ip;
|
||||
Anope::string reverse = user->ip.reverse();
|
||||
|
||||
for (unsigned i = 0; i < this->blacklists.size(); ++i)
|
||||
{
|
||||
const Blacklist &b = this->blacklists[i];
|
||||
|
||||
Anope::string dnsbl_host = reverse.addr() + "." + b.name;
|
||||
Anope::string dnsbl_host = reverse + "." + b.name;
|
||||
DNSBLResolver *res = NULL;
|
||||
try
|
||||
{
|
||||
|
||||
+9
-2
@@ -157,6 +157,11 @@ class MyRedisService : public Provider
|
||||
}
|
||||
|
||||
public:
|
||||
bool IsSocketDead() anope_override
|
||||
{
|
||||
return this->sock && this->sock->flags[SF_DEAD];
|
||||
}
|
||||
|
||||
void SendCommand(RedisSocket *s, Interface *i, const std::vector<Anope::string> &cmds)
|
||||
{
|
||||
std::vector<std::pair<const char *, size_t> > args;
|
||||
@@ -201,9 +206,11 @@ class MyRedisService : public Provider
|
||||
public:
|
||||
bool BlockAndProcess() anope_override
|
||||
{
|
||||
this->sock->ProcessWrite();
|
||||
if (!this->sock->ProcessWrite())
|
||||
this->sock->flags[SF_DEAD] = true;
|
||||
this->sock->SetBlocking(true);
|
||||
this->sock->ProcessRead();
|
||||
if (!this->sock->ProcessRead())
|
||||
this->sock->flags[SF_DEAD] = true;
|
||||
this->sock->SetBlocking(false);
|
||||
return !this->sock->interfaces.empty();
|
||||
}
|
||||
|
||||
+2
-2
@@ -111,13 +111,13 @@ class External : public Mechanism
|
||||
NickCore *nc = certs->FindAccountFromCert(mysess->cert);
|
||||
if (!nc || nc->HasExt("NS_SUSPENDED") || nc->HasExt("UNCONFIRMED"))
|
||||
{
|
||||
Log(Config->GetClient("NickServ"), "sasl") << user << " failed to identify using certificate " << mysess->cert << " using SASL EXTERNAL";
|
||||
Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " failed to identify using certificate " << mysess->cert << " using SASL EXTERNAL";
|
||||
sasl->Fail(sess);
|
||||
delete sess;
|
||||
return;
|
||||
}
|
||||
|
||||
Log(Config->GetClient("NickServ"), "sasl") << user << " identified to account " << nc->display << " using SASL EXTERNAL";
|
||||
Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " identified to account " << nc->display << " using SASL EXTERNAL";
|
||||
sasl->Succeed(sess, nc);
|
||||
delete sess;
|
||||
}
|
||||
|
||||
+15
-14
@@ -107,7 +107,7 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
|
||||
prev = cur;
|
||||
cur.clear();
|
||||
|
||||
int len = 0;
|
||||
size_t len = 0;
|
||||
istag = false;
|
||||
|
||||
if (content[0] == '<')
|
||||
@@ -120,20 +120,21 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
|
||||
len = content.find_first_of('<');
|
||||
}
|
||||
|
||||
if (len)
|
||||
// len must advance
|
||||
if (len == Anope::string::npos || len == 0)
|
||||
break;
|
||||
|
||||
if (istag)
|
||||
{
|
||||
if (istag)
|
||||
{
|
||||
cur = content.substr(1, len - 1);
|
||||
content.erase(0, len + 1);
|
||||
while (!content.empty() && content[0] == ' ')
|
||||
content.erase(content.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = content.substr(0,len);
|
||||
content.erase(0, len);
|
||||
}
|
||||
cur = content.substr(1, len - 1);
|
||||
content.erase(0, len + 1);
|
||||
while (!content.empty() && content[0] == ' ')
|
||||
content.erase(content.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = content.substr(0, len);
|
||||
content.erase(0, len);
|
||||
}
|
||||
}
|
||||
while (istag && !content.empty());
|
||||
|
||||
@@ -108,7 +108,8 @@ class MyXMLRPCEvent : public XMLRPCEvent
|
||||
}
|
||||
reply(out);
|
||||
|
||||
CommandSource source(user, NULL, na ? *na->nc : NULL, &reply, bi);
|
||||
User *u = User::Find(user, true);
|
||||
CommandSource source(user, u, na ? *na->nc : NULL, &reply, bi);
|
||||
Command::Run(source, command);
|
||||
|
||||
if (!out.empty())
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* ircd-hybrid-8 protocol module
|
||||
*
|
||||
* (C) 2003-2017 Anope Team <team@anope.org>
|
||||
* (C) 2012-2016 ircd-hybrid development team
|
||||
* (C) 2012-2017 ircd-hybrid development team
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
@@ -184,12 +184,10 @@ class HybridProto : public IRCDProto
|
||||
UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " TS 6 :" << Me->GetSID();
|
||||
|
||||
/*
|
||||
* As of January 13, 2016, ircd-hybrid-8 does support the following capabilities
|
||||
* As of March 19, 2017, ircd-hybrid-8 does support the following capabilities
|
||||
* which are required to work with IRC-services:
|
||||
*
|
||||
* QS - Can handle quit storm removal
|
||||
* EX - Can do channel +e exemptions
|
||||
* IE - Can do invite exceptions
|
||||
* CHW - Can do channel wall @#
|
||||
* TBURST - Supports topic burst
|
||||
* ENCAP - Supports ENCAP
|
||||
@@ -197,7 +195,7 @@ class HybridProto : public IRCDProto
|
||||
* SVS - Supports services
|
||||
* EOB - Supports End Of Burst message
|
||||
*/
|
||||
UplinkSocket::Message() << "CAPAB :QS EX CHW IE ENCAP TBURST SVS HOPS EOB";
|
||||
UplinkSocket::Message() << "CAPAB :QS CHW ENCAP TBURST SVS HOPS EOB";
|
||||
|
||||
SendServer(Me);
|
||||
|
||||
@@ -662,7 +660,9 @@ class ProtoHybrid : public Module
|
||||
ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r'));
|
||||
ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
|
||||
ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
|
||||
ModeManager::AddChannelMode(new ChannelMode("HIDEBMASKS", 'u'));
|
||||
ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
|
||||
ModeManager::AddChannelMode(new ChannelModeOperOnly("LBAN", 'L'));
|
||||
ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M'));
|
||||
ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O'));
|
||||
ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
|
||||
|
||||
@@ -151,13 +151,14 @@ class InspIRCd12Proto : public IRCDProto
|
||||
|
||||
void SendVhostDel(User *u) anope_override
|
||||
{
|
||||
if (u->HasMode("CLOAK"))
|
||||
this->SendChgHostInternal(u->nick, u->chost);
|
||||
else
|
||||
this->SendChgHostInternal(u->nick, u->host);
|
||||
UserMode *um = ModeManager::FindUserModeByName("CLOAK");
|
||||
|
||||
if (Servers::Capab.count("CHGIDENT") && u->GetIdent() != u->GetVIdent())
|
||||
this->SendChgIdentInternal(u->nick, u->GetIdent());
|
||||
if (um && !u->HasMode(um->name))
|
||||
// Just set +x if we can
|
||||
u->SetMode(NULL, um);
|
||||
else
|
||||
// Try to restore cloaked host
|
||||
this->SendChgHostInternal(u->nick, u->chost);
|
||||
}
|
||||
|
||||
void SendAkill(User *u, XLine *x) anope_override
|
||||
@@ -409,6 +410,11 @@ class InspIRCd12Proto : public IRCDProto
|
||||
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
|
||||
{
|
||||
UplinkSocket::Message(Me) << "METADATA " << uid << " accountname :" << acc;
|
||||
|
||||
if (!vident.empty())
|
||||
UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGIDENT " << uid << " " << vident;
|
||||
if (!vhost.empty())
|
||||
UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGHOST " << uid << " " << vhost;
|
||||
|
||||
SASLUser su;
|
||||
su.uid = uid;
|
||||
|
||||
@@ -174,10 +174,11 @@ class PlexusProto : public IRCDProto
|
||||
UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : message.target.substr(0, 3)) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
|
||||
}
|
||||
|
||||
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
|
||||
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
|
||||
{
|
||||
Server *s = Server::Find(uid.substr(0, 3));
|
||||
UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * * * " << acc;
|
||||
UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * * "
|
||||
<< (vhost.empty() ? "*" : vhost) << " " << acc;
|
||||
}
|
||||
|
||||
void SendSVSNOOP(const Server *server, bool set) anope_override
|
||||
|
||||
@@ -158,7 +158,8 @@ class UnrealIRCdProto : public IRCDProto
|
||||
/* JOIN */
|
||||
void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
|
||||
{
|
||||
UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " :" << user->GetUID();
|
||||
UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name
|
||||
<< " +" << c->GetModes(true, true) << " :" << user->GetUID();
|
||||
if (status)
|
||||
{
|
||||
/* First save the channel status incase uc->Status == status */
|
||||
@@ -204,6 +205,10 @@ class UnrealIRCdProto : public IRCDProto
|
||||
UplinkSocket::Message(Me) << "CHGIDENT " << u->GetUID() << " " << vIdent;
|
||||
if (!vhost.empty())
|
||||
UplinkSocket::Message(Me) << "CHGHOST " << u->GetUID() << " " << vhost;
|
||||
// Internally unreal sets +xt on chghost
|
||||
BotInfo *bi = Config->GetClient("HostServ");
|
||||
u->SetMode(bi, "CLOAK");
|
||||
u->SetMode(bi, "VHOST");
|
||||
}
|
||||
|
||||
void SendConnect() anope_override
|
||||
@@ -227,6 +232,15 @@ class UnrealIRCdProto : public IRCDProto
|
||||
SendServer(Me);
|
||||
}
|
||||
|
||||
void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) anope_override
|
||||
{
|
||||
Anope::string mechlist;
|
||||
for (unsigned i = 0; i < mechanisms.size(); ++i)
|
||||
mechlist += "," + mechanisms[i];
|
||||
|
||||
UplinkSocket::Message() << "MD client " << Me->GetName() << " saslmechlist :" << (mechanisms.empty() ? "" : mechlist.substr(1));
|
||||
}
|
||||
|
||||
/* SVSHOLD - set */
|
||||
void SendSVSHold(const Anope::string &nick, time_t t) anope_override
|
||||
{
|
||||
@@ -352,22 +366,8 @@ class UnrealIRCdProto : public IRCDProto
|
||||
|
||||
void SendChannel(Channel *c) anope_override
|
||||
{
|
||||
/* Unreal does not support updating a channels TS without actually joining a user,
|
||||
* so we will join and part us now
|
||||
*/
|
||||
BotInfo *bi = c->ci->WhoSends();
|
||||
if (!bi)
|
||||
;
|
||||
else if (c->FindUser(bi) == NULL)
|
||||
{
|
||||
bi->Join(c);
|
||||
bi->Part(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
bi->Part(c);
|
||||
bi->Join(c);
|
||||
}
|
||||
UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name
|
||||
<< " +" << c->GetModes(true, true) << " :";
|
||||
}
|
||||
|
||||
void SendSASLMessage(const SASL::Message &message) anope_override
|
||||
|
||||
@@ -377,34 +377,36 @@ class ChanServCore : public Module, public ChanServService
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnPreUplinkSync(Server *serv) anope_override
|
||||
void OnPostInit() anope_override
|
||||
{
|
||||
if (!persist)
|
||||
return;
|
||||
|
||||
ChannelMode *perm = ModeManager::FindChannelModeByName("PERM");
|
||||
|
||||
/* Find all persistent channels and create them, as we are about to finish burst to our uplink */
|
||||
for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
|
||||
{
|
||||
ChannelInfo *ci = it->second;
|
||||
if (persist->HasExt(ci))
|
||||
{
|
||||
bool c;
|
||||
ci->c = Channel::FindOrCreate(ci->name, c, ci->time_registered);
|
||||
if (!persist->HasExt(ci))
|
||||
continue;
|
||||
|
||||
if (ModeManager::FindChannelModeByName("PERM") != NULL)
|
||||
bool c;
|
||||
ci->c = Channel::FindOrCreate(ci->name, c, ci->time_registered);
|
||||
ci->c->syncing |= created;
|
||||
|
||||
if (perm)
|
||||
{
|
||||
ci->c->SetMode(NULL, perm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ci->bi)
|
||||
ci->WhoSends()->Assign(NULL, ci);
|
||||
if (ci->c->FindUser(ci->bi) == NULL)
|
||||
{
|
||||
if (c)
|
||||
IRCD->SendChannel(ci->c);
|
||||
ci->c->SetMode(NULL, "PERM");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ci->bi)
|
||||
ci->WhoSends()->Assign(NULL, ci);
|
||||
if (ci->c->FindUser(ci->bi) == NULL)
|
||||
{
|
||||
ChannelStatus status(BotModes());
|
||||
ci->bi->Join(ci->c, &status);
|
||||
}
|
||||
ChannelStatus status(BotModes());
|
||||
ci->bi->Join(ci->c, &status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,13 +493,6 @@ class NickServCore : public Module, public NickServService
|
||||
"Accounts that are not used anymore are subject to\n"
|
||||
"the automatic expiration, i.e. they will be deleted\n"
|
||||
"after %d days if not used."), nickserv_expire / 86400);
|
||||
source.Reply(_(" \n"
|
||||
"\002NOTICE:\002 This service is intended to provide a way for\n"
|
||||
"IRC users to ensure their identity is not compromised.\n"
|
||||
"It is \002NOT\002 intended to facilitate \"stealing\" of\n"
|
||||
"nicknames or other malicious actions. Abuse of %s\n"
|
||||
"will result in, at minimum, loss of the abused\n"
|
||||
"nickname(s)."), NickServ->nick.c_str());
|
||||
}
|
||||
|
||||
void OnNickCoreCreate(NickCore *nc)
|
||||
|
||||
@@ -55,7 +55,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
params.push_back("DEL");
|
||||
params.push_back(message.get_data["mask"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/access", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/access", params, replacements);
|
||||
}
|
||||
else if (message.post_data["mask"].empty() == false && message.post_data["access"].empty() == false && message.post_data["provider"].empty() == false)
|
||||
{
|
||||
@@ -69,7 +69,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
params.push_back(message.post_data["mask"]);
|
||||
params.push_back(message.post_data["access"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/access", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/access", params, replacements);
|
||||
}
|
||||
else if (provider == "chanserv/xop")
|
||||
{
|
||||
@@ -78,7 +78,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
params.push_back("ADD");
|
||||
params.push_back(message.post_data["mask"]);
|
||||
|
||||
WebPanel::RunCommandWithName(na->nc, "ChanServ", "chanserv/xop", message.post_data["access"], params, replacements);
|
||||
WebPanel::RunCommandWithName(client, na->nc, "ChanServ", "chanserv/xop", message.post_data["access"], params, replacements);
|
||||
}
|
||||
else if (provider == "chanserv/flags")
|
||||
{
|
||||
@@ -88,7 +88,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
params.push_back(message.post_data["mask"]);
|
||||
params.push_back(message.post_data["access"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/flags", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/flags", params, replacements);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,9 +103,9 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
{
|
||||
ChanAccess *access = ci->GetAccess(i);
|
||||
|
||||
replacements["MASKS"] = HTTPUtils::Escape(access->Mask());
|
||||
replacements["ACCESSES"] = HTTPUtils::Escape(access->AccessSerialize());
|
||||
replacements["CREATORS"] = HTTPUtils::Escape(access->creator);
|
||||
replacements["MASKS"] = access->Mask();
|
||||
replacements["ACCESSES"] = access->AccessSerialize();
|
||||
replacements["CREATORS"] = access->creator;
|
||||
}
|
||||
|
||||
if (Service::FindService("Command", "chanserv/access"))
|
||||
|
||||
@@ -53,7 +53,7 @@ bool WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st
|
||||
params.push_back("DEL");
|
||||
params.push_back(message.get_data["mask"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/akick", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/akick", params, replacements);
|
||||
}
|
||||
else if (message.post_data["mask"].empty() == false)
|
||||
{
|
||||
@@ -64,7 +64,7 @@ bool WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st
|
||||
if (message.post_data["reason"].empty() == false)
|
||||
params.push_back(message.post_data["reason"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/akick", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/akick", params, replacements);
|
||||
}
|
||||
|
||||
replacements["ESCAPED_CHANNEL"] = HTTPUtils::URLEncode(chname);
|
||||
@@ -74,11 +74,11 @@ bool WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st
|
||||
AutoKick *akick = ci->GetAkick(i);
|
||||
|
||||
if (akick->nc)
|
||||
replacements["MASKS"] = HTTPUtils::Escape(akick->nc->display);
|
||||
replacements["MASKS"] = akick->nc->display;
|
||||
else
|
||||
replacements["MASKS"] = HTTPUtils::Escape(akick->mask);
|
||||
replacements["CREATORS"] = HTTPUtils::Escape(akick->creator);
|
||||
replacements["REASONS"] = HTTPUtils::Escape(akick->reason);
|
||||
replacements["MASKS"] = akick->mask;
|
||||
replacements["CREATORS"] = akick->creator;
|
||||
replacements["REASONS"] = akick->reason;
|
||||
}
|
||||
|
||||
Page.Serve(server, page_name, client, message, reply, replacements);
|
||||
|
||||
@@ -25,7 +25,7 @@ bool WebCPanel::ChanServ::Drop::OnRequest(HTTPProvider *server, const Anope::str
|
||||
params.push_back(channel);
|
||||
params.push_back(channel);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/drop", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/drop", params, replacements);
|
||||
}
|
||||
else
|
||||
replacements["MESSAGES"] = "Invalid Confirmation";
|
||||
|
||||
@@ -82,7 +82,7 @@ bool WebCPanel::ChanServ::Modes::OnRequest(HTTPProvider *server, const Anope::st
|
||||
params.push_back("SET");
|
||||
params.push_back("-" + Anope::string(cm->mchar));
|
||||
params.push_back(message.get_data["mask"]);
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/mode", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/mode", params, replacements);
|
||||
}
|
||||
else if (message.post_data["mask"].empty() == false)
|
||||
{
|
||||
@@ -91,12 +91,12 @@ bool WebCPanel::ChanServ::Modes::OnRequest(HTTPProvider *server, const Anope::st
|
||||
params.push_back("SET");
|
||||
params.push_back("+" + Anope::string(cm->mchar));
|
||||
params.push_back(message.post_data["mask"]);
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "ChanServ", "chanserv/mode", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/mode", params, replacements);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> v = c->GetModeList(cm->name);
|
||||
for (unsigned int i = 0; i < v.size(); ++i)
|
||||
replacements["MASKS"] = HTTPUtils::Escape(v[i]);
|
||||
replacements["MASKS"] = v[i];
|
||||
}
|
||||
|
||||
Page.Serve(server, page_name, client, message, reply, replacements);
|
||||
|
||||
@@ -102,7 +102,7 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
|
||||
}
|
||||
}
|
||||
|
||||
replacements["CHANNEL"] = HTTPUtils::Escape(ci->name);
|
||||
replacements["CHANNEL"] = ci->name;
|
||||
replacements["CHANNEL_ESCAPED"] = HTTPUtils::URLEncode(ci->name);
|
||||
if (ci->GetFounder())
|
||||
replacements["FOUNDER"] = ci->GetFounder()->display;
|
||||
@@ -114,8 +114,8 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
|
||||
|
||||
if (!ci->last_topic.empty())
|
||||
{
|
||||
replacements["LAST_TOPIC"] = HTTPUtils::Escape(ci->last_topic);
|
||||
replacements["LAST_TOPIC_SETTER"] = HTTPUtils::Escape(ci->last_topic_setter);
|
||||
replacements["LAST_TOPIC"] = ci->last_topic;
|
||||
replacements["LAST_TOPIC_SETTER"] = ci->last_topic_setter;
|
||||
}
|
||||
|
||||
if (can_set)
|
||||
|
||||
@@ -21,7 +21,7 @@ bool WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &pa
|
||||
if (!email.empty())
|
||||
params.push_back(email);
|
||||
|
||||
WebPanel::RunCommand(user, NULL, "NickServ", "nickserv/register", params, replacements);
|
||||
WebPanel::RunCommand(client, user, NULL, "NickServ", "nickserv/register", params, replacements);
|
||||
}
|
||||
|
||||
TemplateFileServer page("confirm.html");
|
||||
|
||||
@@ -18,7 +18,7 @@ bool WebCPanel::HostServ::Request::OnRequest(HTTPProvider *server, const Anope::
|
||||
std::vector<Anope::string> params;
|
||||
params.push_back(HTTPUtils::URLDecode(message.post_data["req"]));
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "HostServ", "hostserv/request", params, replacements, "CMDR");
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "HostServ", "hostserv/request", params, replacements, "CMDR");
|
||||
}
|
||||
|
||||
if (na->HasVhost())
|
||||
|
||||
@@ -36,6 +36,14 @@ class WebpanelRequest : public IdentifyRequest
|
||||
return;
|
||||
}
|
||||
|
||||
// Rate limit logins to 1/sec
|
||||
time_t *last_login = na->nc->GetExt<time_t>("webcpanel_last_login");
|
||||
if (last_login != NULL && Anope::CurTime == *last_login)
|
||||
{
|
||||
this->OnFail();
|
||||
return;
|
||||
}
|
||||
|
||||
Anope::string id;
|
||||
for (int i = 0; i < 64; ++i)
|
||||
{
|
||||
@@ -48,6 +56,7 @@ class WebpanelRequest : public IdentifyRequest
|
||||
|
||||
na->Extend<Anope::string>("webcpanel_id", id);
|
||||
na->Extend<Anope::string>("webcpanel_ip", client->GetIP());
|
||||
na->nc->Extend<time_t>("webcpanel_last_login", Anope::CurTime);
|
||||
|
||||
{
|
||||
HTTPReply::cookie c;
|
||||
@@ -91,6 +100,30 @@ bool WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page
|
||||
if (!user.empty() && !pass.empty())
|
||||
{
|
||||
// Rate limit check.
|
||||
Anope::string ip = client->clientaddr.addr();
|
||||
|
||||
Anope::hash_map<time_t>::iterator it = last_login_attempt.find(ip);
|
||||
if (it != last_login_attempt.end())
|
||||
{
|
||||
time_t last_time = it->second;
|
||||
|
||||
if (last_time == Anope::CurTime)
|
||||
{
|
||||
replacements["INVALID_LOGIN"] = "Rate limited";
|
||||
TemplateFileServer page("login.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// don't let ip hash grow too long
|
||||
if (Anope::CurTime > last_clear + FLUSH_TIME)
|
||||
{
|
||||
last_login_attempt.clear();
|
||||
last_clear = Anope::CurTime;
|
||||
}
|
||||
|
||||
last_login_attempt[ip] = Anope::CurTime;
|
||||
|
||||
WebpanelRequest *req = new WebpanelRequest(me, reply, message, server, page_name, client, replacements, user, pass);
|
||||
FOREACH_MOD(OnCheckAuthentication, (NULL, req));
|
||||
|
||||
@@ -12,8 +12,13 @@ namespace WebCPanel
|
||||
|
||||
class Index : public WebPanelPage
|
||||
{
|
||||
static const int FLUSH_TIME = 60;
|
||||
|
||||
Anope::hash_map<time_t> last_login_attempt;
|
||||
time_t last_clear;
|
||||
|
||||
public:
|
||||
Index(const Anope::string &u) : WebPanelPage(u) { }
|
||||
Index(const Anope::string &u) : WebPanelPage(u), last_clear(0) { }
|
||||
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st
|
||||
params.push_back(HTTPUtils::URLDecode(message.post_data["receiver"]));
|
||||
params.push_back(HTTPUtils::URLDecode(message.post_data["message"]));
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "MemoServ", "memoserv/send", params, replacements, "CMDR");
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "MemoServ", "memoserv/send", params, replacements, "CMDR");
|
||||
}
|
||||
if (message.get_data.count("del") > 0 && message.get_data.count("number") > 0)
|
||||
{
|
||||
@@ -66,7 +66,7 @@ bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st
|
||||
params.push_back(chname);
|
||||
params.push_back(message.get_data["number"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "MemoServ", "memoserv/del", params, replacements, "CMDR");
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "MemoServ", "memoserv/del", params, replacements, "CMDR");
|
||||
}
|
||||
if (message.get_data.count("read") > 0 && message.get_data.count("number") > 0)
|
||||
{
|
||||
@@ -101,7 +101,7 @@ bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st
|
||||
replacements["NUMBER"] = stringify(i+1);
|
||||
replacements["SENDER"] = m->sender;
|
||||
replacements["TIME"] = Anope::strftime(m->time);
|
||||
replacements["TEXT"] = HTTPUtils::Escape(m->text);
|
||||
replacements["TEXT"] = m->text;
|
||||
if (m->unread)
|
||||
replacements["UNREAD"] = "YES";
|
||||
else
|
||||
|
||||
@@ -19,7 +19,7 @@ bool WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
params.push_back("ADD");
|
||||
params.push_back(message.post_data["access"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
|
||||
}
|
||||
else if (message.get_data.count("del") > 0 && message.get_data.count("mask") > 0)
|
||||
{
|
||||
@@ -27,7 +27,7 @@ bool WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
params.push_back("DEL");
|
||||
params.push_back(message.get_data["mask"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < na->nc->access.size(); ++i)
|
||||
|
||||
@@ -20,7 +20,7 @@ bool WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::str
|
||||
params.push_back("ADD");
|
||||
params.push_back(message.post_data["certfp"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "NickServ", "nickserv/cert", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/cert", params, replacements);
|
||||
}
|
||||
else if (message.get_data.count("del") > 0 && message.get_data.count("mask") > 0)
|
||||
{
|
||||
@@ -28,7 +28,7 @@ bool WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::str
|
||||
params.push_back("DEL");
|
||||
params.push_back(message.get_data["mask"]);
|
||||
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "NickServ", "nickserv/cert", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/cert", params, replacements);
|
||||
}
|
||||
|
||||
NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
|
||||
|
||||
@@ -84,9 +84,9 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
|
||||
}
|
||||
}
|
||||
|
||||
replacements["DISPLAY"] = HTTPUtils::Escape(na->nc->display);
|
||||
replacements["DISPLAY"] = na->nc->display;
|
||||
if (na->nc->email.empty() == false)
|
||||
replacements["EMAIL"] = HTTPUtils::Escape(na->nc->email);
|
||||
replacements["EMAIL"] = na->nc->email;
|
||||
replacements["TIME_REGISTERED"] = Anope::strftime(na->time_registered, na->nc);
|
||||
if (na->HasVhost())
|
||||
{
|
||||
@@ -97,7 +97,7 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
|
||||
}
|
||||
Anope::string *greet = na->nc->GetExt<Anope::string>("greet");
|
||||
if (greet)
|
||||
replacements["GREET"] = HTTPUtils::Escape(*greet);
|
||||
replacements["GREET"] = *greet;
|
||||
if (na->nc->HasExt("AUTOOP"))
|
||||
replacements["AUTOOP"];
|
||||
if (na->nc->HasExt("NS_PRIVATE"))
|
||||
|
||||
@@ -34,7 +34,7 @@ bool WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::st
|
||||
cmdstr << " " << HTTPUtils::URLDecode(message.post_data["mask"]);
|
||||
cmdstr << " " << HTTPUtils::URLDecode(message.post_data["reason"]);
|
||||
params.push_back(cmdstr.str());
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "OperServ", "operserv/akill", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "OperServ", "operserv/akill", params, replacements);
|
||||
}
|
||||
|
||||
if (message.get_data["del"] == "1" && message.get_data.count("number") > 0)
|
||||
@@ -42,7 +42,7 @@ bool WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::st
|
||||
std::vector<Anope::string> params;
|
||||
params.push_back("DEL");
|
||||
params.push_back(HTTPUtils::URLDecode(message.get_data["number"]));
|
||||
WebPanel::RunCommand(na->nc->display, na->nc, "OperServ", "operserv/akill", params, replacements);
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "OperServ", "operserv/akill", params, replacements);
|
||||
}
|
||||
|
||||
for (unsigned i = 0, end = akills->GetCount(); i < end; ++i)
|
||||
|
||||
@@ -238,7 +238,11 @@ void TemplateFileServer::Serve(HTTPProvider *server, const Anope::string &page_n
|
||||
|
||||
if (ifok && forok)
|
||||
{
|
||||
const Anope::string &replacement = FindReplacement(r, content.substr(0, f - 1));
|
||||
Anope::string replacement = FindReplacement(r, content.substr(0, f - 1));
|
||||
|
||||
// htmlescape all text replaced onto the page
|
||||
replacement = HTTPUtils::Escape(replacement);
|
||||
|
||||
finished += replacement;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class ModuleWebCPanel : public Module
|
||||
ServiceReference<HTTPProvider> provider;
|
||||
Panel panel;
|
||||
PrimitiveExtensibleItem<Anope::string> id, ip;
|
||||
PrimitiveExtensibleItem<time_t> last_login;
|
||||
|
||||
StaticFileServer style_css, logo_png, cubes_png, favicon_ico;
|
||||
|
||||
@@ -44,7 +45,8 @@ class ModuleWebCPanel : public Module
|
||||
|
||||
public:
|
||||
ModuleWebCPanel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
|
||||
panel(this, "webcpanel"), id(this, "webcpanel_id"), ip(this, "webcpanel_ip"),
|
||||
panel(this, "webcpanel"),
|
||||
id(this, "webcpanel_id"), ip(this, "webcpanel_ip"), last_login(this, "webcpanel_last_login"),
|
||||
style_css("style.css", "/static/style.css", "text/css"), logo_png("logo.png", "/static/logo.png", "image/png"), cubes_png("cubes.png", "/static/cubes.png", "image/png"), favicon_ico("favicon.ico", "/favicon.ico", "image/x-icon"),
|
||||
index("/"), logout("/logout"), _register("/register"), confirm("/confirm"),
|
||||
nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_access("NickServ", "/nickserv/access"), nickserv_alist("NickServ", "/nickserv/alist"),
|
||||
@@ -231,7 +233,7 @@ class ModuleWebCPanel : public Module
|
||||
|
||||
namespace WebPanel
|
||||
{
|
||||
void RunCommand(const Anope::string &user, NickCore *nc, const Anope::string &service, const Anope::string &c, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key)
|
||||
void RunCommand(HTTPClient *client, const Anope::string &user, NickCore *nc, const Anope::string &service, const Anope::string &c, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key)
|
||||
{
|
||||
ServiceReference<Command> cmd("Command", c);
|
||||
if (!cmd)
|
||||
@@ -266,12 +268,15 @@ namespace WebPanel
|
||||
my_reply(r, key);
|
||||
|
||||
CommandSource source(user, NULL, nc, &my_reply, bi);
|
||||
source.ip = client->clientaddr.addr();
|
||||
|
||||
CommandInfo info;
|
||||
info.name = c;
|
||||
|
||||
cmd->Run(source, "", info, params);
|
||||
}
|
||||
|
||||
void RunCommandWithName(NickCore *nc, const Anope::string &service, const Anope::string &c, const Anope::string &cmdname, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key)
|
||||
void RunCommandWithName(HTTPClient *client, NickCore *nc, const Anope::string &service, const Anope::string &c, const Anope::string &cmdname, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key)
|
||||
{
|
||||
ServiceReference<Command> cmd("Command", c);
|
||||
if (!cmd)
|
||||
@@ -303,6 +308,7 @@ namespace WebPanel
|
||||
my_reply(r, key);
|
||||
|
||||
CommandSource source(nc->display, NULL, nc, &my_reply, bi);
|
||||
source.ip = client->clientaddr.addr();
|
||||
|
||||
cmd->Run(source, cmdname, *info, params);
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ class WebPanelProtectedPage : public WebPanelPage
|
||||
namespace WebPanel
|
||||
{
|
||||
/** Run a command
|
||||
* @param client HTTP client command is being issued for
|
||||
* @param User name to run command as, probably nc->display unless nc == NULL
|
||||
* @param nc Nick core to run command from
|
||||
* @param service Service for source.owner and source.service
|
||||
@@ -151,9 +152,9 @@ namespace WebPanel
|
||||
* @param r Replacements, reply from command goes back here into key
|
||||
* @param key The key to put the replies into r
|
||||
*/
|
||||
extern void RunCommand(const Anope::string &user, NickCore *nc, const Anope::string &service, const Anope::string &c, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key = "MESSAGES");
|
||||
extern void RunCommand(HTTPClient *client, const Anope::string &user, NickCore *nc, const Anope::string &service, const Anope::string &c, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key = "MESSAGES");
|
||||
|
||||
extern void RunCommandWithName(NickCore *nc, const Anope::string &service, const Anope::string &c, const Anope::string &cmdname, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key = "MESSAGES");
|
||||
extern void RunCommandWithName(HTTPClient *client, NickCore *nc, const Anope::string &service, const Anope::string &c, const Anope::string &cmdname, std::vector<Anope::string> ¶ms, TemplateFileServer::Replacements &r, const Anope::string &key = "MESSAGES");
|
||||
}
|
||||
|
||||
#include "pages/index.h"
|
||||
|
||||
+14
-9
@@ -464,15 +464,21 @@ void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::stri
|
||||
SetMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
|
||||
}
|
||||
|
||||
void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
|
||||
void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &wparam, bool enforce_mlock)
|
||||
{
|
||||
if (!cm)
|
||||
return;
|
||||
|
||||
/* Don't unset modes that arent set */
|
||||
if ((cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && !HasMode(cm->name))
|
||||
return;
|
||||
|
||||
/* Unwrap to be sure we have the internal representation */
|
||||
Anope::string param = wparam;
|
||||
cm = cm->Unwrap(param);
|
||||
|
||||
/* Don't unset status that aren't set */
|
||||
else if (cm->type == MODE_STATUS)
|
||||
if (cm->type == MODE_STATUS)
|
||||
{
|
||||
User *u = User::Find(param);
|
||||
if (!u || !HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm)))
|
||||
@@ -485,13 +491,12 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶
|
||||
}
|
||||
|
||||
/* Get the param to send, if we need it */
|
||||
Anope::string realparam = param;
|
||||
if (cm->type == MODE_PARAM)
|
||||
{
|
||||
realparam.clear();
|
||||
param.clear();
|
||||
ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
|
||||
if (!cmp->minus_no_arg)
|
||||
this->GetParam(cmp->name, realparam);
|
||||
this->GetParam(cmp->name, param);
|
||||
}
|
||||
|
||||
if (Me->IsSynced())
|
||||
@@ -505,12 +510,12 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶
|
||||
this->chanserv_modecount++;
|
||||
}
|
||||
|
||||
Anope::string wparam = realparam;
|
||||
ChannelMode *wcm = cm->Wrap(wparam);
|
||||
/* Wrap to get ircd representation */
|
||||
ChannelMode *wcm = cm->Wrap(param);
|
||||
|
||||
ModeManager::StackerAdd(bi, this, wcm, false, wparam);
|
||||
ModeManager::StackerAdd(bi, this, wcm, false, param);
|
||||
MessageSource ms(bi);
|
||||
RemoveModeInternal(ms, wcm, wparam, enforce_mlock);
|
||||
RemoveModeInternal(ms, wcm, param, enforce_mlock);
|
||||
}
|
||||
|
||||
void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock)
|
||||
|
||||
+17
-3
@@ -157,7 +157,13 @@ Conf::Conf() : Block("")
|
||||
Block *serverinfo = this->GetBlock("serverinfo"), *options = this->GetBlock("options"),
|
||||
*mail = this->GetBlock("mail"), *networkinfo = this->GetBlock("networkinfo");
|
||||
|
||||
ValidateNotEmpty("serverinfo", "name", serverinfo->Get<const Anope::string>("name"));
|
||||
const Anope::string &servername = serverinfo->Get<Anope::string>("name");
|
||||
|
||||
ValidateNotEmpty("serverinfo", "name", servername);
|
||||
|
||||
if (servername.find(' ') != Anope::string::npos || servername.find('.') == Anope::string::npos)
|
||||
throw ConfigException("serverinfo:name is not a valid server name");
|
||||
|
||||
ValidateNotEmpty("serverinfo", "description", serverinfo->Get<const Anope::string>("description"));
|
||||
ValidateNotEmpty("serverinfo", "pid", serverinfo->Get<const Anope::string>("pid"));
|
||||
ValidateNotEmpty("serverinfo", "motd", serverinfo->Get<const Anope::string>("motd"));
|
||||
@@ -205,6 +211,9 @@ Conf::Conf() : Block("")
|
||||
ValidateNotZero("uplink", "port", port);
|
||||
ValidateNotEmpty("uplink", "password", password);
|
||||
|
||||
if (password.find(' ') != Anope::string::npos || password[0] == ':')
|
||||
throw ConfigException("uplink:password is not valid");
|
||||
|
||||
this->Uplinks.push_back(Uplink(host, port, password, ipv6));
|
||||
}
|
||||
|
||||
@@ -656,6 +665,11 @@ const Anope::string &File::GetName() const
|
||||
return this->name;
|
||||
}
|
||||
|
||||
Anope::string File::GetPath() const
|
||||
{
|
||||
return (this->executable ? "" : Anope::ConfigDir + "/") + this->name;
|
||||
}
|
||||
|
||||
bool File::IsOpen() const
|
||||
{
|
||||
return this->fp != NULL;
|
||||
@@ -713,14 +727,14 @@ void Conf::LoadConf(File &file)
|
||||
return;
|
||||
|
||||
if (!file.Open())
|
||||
throw ConfigException("File " + file.GetName() + " could not be opened.");
|
||||
throw ConfigException("File " + file.GetPath() + " could not be opened.");
|
||||
|
||||
Anope::string itemname, wordbuffer;
|
||||
std::stack<Block *> block_stack;
|
||||
int linenumber = 0;
|
||||
bool in_word = false, in_quote = false, in_comment = false;
|
||||
|
||||
Log(LOG_DEBUG) << "Start to read conf " << file.GetName();
|
||||
Log(LOG_DEBUG) << "Start to read conf " << file.GetPath();
|
||||
// Start reading characters...
|
||||
while (!file.End())
|
||||
{
|
||||
|
||||
@@ -553,6 +553,8 @@ void Anope::Init(int ac, char **av)
|
||||
static_cast<void>(MOD_RESULT);
|
||||
Log() << "Databases loaded";
|
||||
|
||||
FOREACH_MOD(OnPostInit, ());
|
||||
|
||||
for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
|
||||
it->second->Sync();
|
||||
|
||||
|
||||
+7
-2
@@ -146,8 +146,13 @@ Anope::string Log::FormatSource() const
|
||||
else if (nc)
|
||||
return nc->display;
|
||||
else if (source)
|
||||
return source->GetNick();
|
||||
return "<unknown>";
|
||||
{
|
||||
Anope::string nickbuf = source->GetNick();
|
||||
if (!nickbuf.empty() && !source->ip.empty())
|
||||
nickbuf += " (" + source->ip + ")";
|
||||
return nickbuf;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Anope::string Log::FormatCommand() const
|
||||
|
||||
+3
-3
@@ -647,7 +647,7 @@ void ModeManager::ProcessModes()
|
||||
|
||||
std::list<Anope::string> ModeStrings = BuildModeStrings(s);
|
||||
for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
|
||||
IRCD->SendMode(s->bi, u, lit->c_str());
|
||||
IRCD->SendMode(s->bi, u, "%s", lit->c_str());
|
||||
delete it->second;
|
||||
}
|
||||
UserStackerObjects.clear();
|
||||
@@ -662,7 +662,7 @@ void ModeManager::ProcessModes()
|
||||
|
||||
std::list<Anope::string> ModeStrings = BuildModeStrings(s);
|
||||
for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
|
||||
IRCD->SendMode(s->bi, c, lit->c_str());
|
||||
IRCD->SendMode(s->bi, c, "%s", lit->c_str());
|
||||
delete it->second;
|
||||
}
|
||||
ChannelStackerObjects.clear();
|
||||
@@ -678,7 +678,7 @@ static void StackerDel(std::map<T *, StackerInfo *> &map, T *obj)
|
||||
StackerInfo *si = it->second;
|
||||
std::list<Anope::string> ModeStrings = BuildModeStrings(si);
|
||||
for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
|
||||
IRCD->SendMode(si->bi, obj, lit->c_str());
|
||||
IRCD->SendMode(si->bi, obj, "%s", lit->c_str());
|
||||
|
||||
delete si;
|
||||
map.erase(it);
|
||||
|
||||
+2
-2
@@ -50,10 +50,10 @@ NickAlias::NickAlias(const Anope::string &nickname, NickCore* nickcore) : Serial
|
||||
|
||||
NickAlias::~NickAlias()
|
||||
{
|
||||
UnsetExtensibles();
|
||||
|
||||
FOREACH_MOD(OnDelNick, (this));
|
||||
|
||||
UnsetExtensibles();
|
||||
|
||||
/* Accept nicks that have no core, because of database load functions */
|
||||
if (this->nc)
|
||||
{
|
||||
|
||||
+2
-2
@@ -37,10 +37,10 @@ NickCore::NickCore(const Anope::string &coredisplay) : Serializable("NickCore"),
|
||||
|
||||
NickCore::~NickCore()
|
||||
{
|
||||
UnsetExtensibles();
|
||||
|
||||
FOREACH_MOD(OnDelCore, (this));
|
||||
|
||||
UnsetExtensibles();
|
||||
|
||||
if (!this->chanaccess->empty())
|
||||
Log(LOG_DEBUG) << "Non-empty chanaccess list in destructor!";
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
|
||||
std::vector<Oper *> Oper::opers;
|
||||
|
||||
Oper::Oper(const Anope::string &n, OperType *o) : name(n), ot(o), require_oper(false)
|
||||
Oper::Oper(const Anope::string &n, OperType *o) : name(n), ot(o), require_oper(true)
|
||||
{
|
||||
opers.push_back(this);
|
||||
}
|
||||
|
||||
+4
-5
@@ -33,9 +33,8 @@ AutoKick::~AutoKick()
|
||||
if (it != this->ci->akick->end())
|
||||
this->ci->akick->erase(it);
|
||||
|
||||
const NickAlias *na = NickAlias::Find(this->mask);
|
||||
if (na != NULL)
|
||||
na->nc->RemoveChannelReference(this->ci);
|
||||
if (nc)
|
||||
nc->RemoveChannelReference(this->ci);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,10 +140,10 @@ ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"),
|
||||
|
||||
ChannelInfo::~ChannelInfo()
|
||||
{
|
||||
UnsetExtensibles();
|
||||
|
||||
FOREACH_MOD(OnDelChan, (this));
|
||||
|
||||
UnsetExtensibles();
|
||||
|
||||
Log(LOG_DEBUG) << "Deleting channel " << this->name;
|
||||
|
||||
if (this->c)
|
||||
|
||||
@@ -95,6 +95,41 @@ Anope::string sockaddrs::addr() const
|
||||
return "";
|
||||
}
|
||||
|
||||
Anope::string sockaddrs::reverse() const
|
||||
{
|
||||
char address[128];
|
||||
|
||||
switch (sa.sa_family)
|
||||
{
|
||||
case AF_INET6:
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
unsigned reverse_ip_count = 0;
|
||||
for (int j = 15; j >= 0; --j)
|
||||
{
|
||||
address[reverse_ip_count++] = hex[sa6.sin6_addr.s6_addr[j] & 0xF];
|
||||
address[reverse_ip_count++] = '.';
|
||||
address[reverse_ip_count++] = hex[sa6.sin6_addr.s6_addr[j] >> 4];
|
||||
address[reverse_ip_count++] = '.';
|
||||
}
|
||||
/* Remove the last '.' */
|
||||
address[reverse_ip_count - 1] = 0;
|
||||
return address;
|
||||
}
|
||||
case AF_INET:
|
||||
{
|
||||
unsigned long forward = sa4.sin_addr.s_addr;
|
||||
in_addr rev;
|
||||
rev.s_addr = forward << 24 | (forward & 0xFF00) << 8 | (forward & 0xFF0000) >> 8 | forward >> 24;
|
||||
if (inet_ntop(AF_INET, &rev, address, sizeof(address)))
|
||||
return address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool sockaddrs::ipv6() const
|
||||
{
|
||||
return sa.sa_family == AF_INET6;
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
|
||||
VERSION_MAJOR=2
|
||||
VERSION_MINOR=0
|
||||
VERSION_PATCH=5
|
||||
VERSION_PATCH=6
|
||||
VERSION_EXTRA=""
|
||||
|
||||
Reference in New Issue
Block a user