1
0
mirror of https://github.com/anope/anope.git synced 2026-06-15 03:44:45 +02:00

Compare commits

...

61 Commits

Author SHA1 Message Date
Adam 0574de2d22 Anope 2.0.6 Release 2017-12-11 11:46:10 -05:00
Adam c9c53dbe61 Add README.md, for github 2017-11-19 17:28:05 -05:00
Adam a084245822 README: remove some outdated links 2017-11-19 17:28:05 -05:00
Robby 77e3f062da Update the dutch language file. 2017-11-17 23:56:15 +01:00
Adam 8bb3067e42 Update Changes and Changes.conf 2017-10-12 19:58:02 -04:00
Adam 0c469abe4a Call OnDelChan prior to unsetting extensibles
cs_set uses this to set -P on permanent channels if they are persistent.

Also move similar event in nickcore/nickalias destruction
2017-10-12 19:37:06 -04:00
Adam d63e32a579 No longer try to create persistent channels on the fly
Change initial channel creation to on post init so it will be part of
the burst.
2017-10-12 19:30:48 -04:00
Adam f13c450b93 Add post init event 2017-10-12 19:28:34 -04:00
Adam e95c07291a unreal4: send sjoin with empty users in SendChannel 2017-10-12 19:28:12 -04:00
Adam 2963fc0a1d unreal4: send modes in sjoin 2017-10-12 19:27:51 -04:00
Adam 5d309d46e1 plexus: fix overriding SendSVSLogin 2017-10-10 21:19:23 -04:00
Adam 2e7fcd3098 Merge pull request #199 from syzop/2.0+unrealsaslmechs
Advertise SASL mechanisms to UnrealIRCd servers.
2017-10-09 11:29:55 -04:00
Adam 884759aed4 Merge pull request #200 from syzop/2.0+saslbydefault
Load sasl module by default.
2017-10-09 11:23:09 -04:00
Bram Matthys 2ec65023a6 Load sasl module by default. 2017-10-09 10:31:21 +02:00
Bram Matthys 0093f3fa44 Advertise SASL mechanisms to UnrealIRCd servers. 2017-10-09 10:22:50 +02:00
Adam 2ad76278dd Use full path to file for conf.cpp file could not be opened error message 2017-08-05 18:31:57 -04:00
Tim Gunter 23e59d9f2c Allow calls to XMLRPC to impersonate supplied user, if online 2017-07-28 09:08:40 -04:00
Adam 3cb9e0b97c m_xmlrpc: fix incorrect string find usage 2017-07-24 20:30:34 -04:00
Adam 0b7b6d9d6d ns_group: don't require a user to group 2017-07-24 10:04:07 -04:00
Adam 56e6efbe8f Default require_oper to true. Fixes os_oper unserializer because it doesn't set it. 2017-07-02 18:03:36 -04:00
Adam feed624cdc webcpanel: rate limit login attempts 2017-06-05 18:44:48 -04:00
Adam 1a6f42b994 webcpanel: escape values in template_fileserver
Remove other escapes to prevent double escape.

Not all replaced values were escaped, such as replies from commands.
2017-06-05 10:11:22 -04:00
Adam 04f49225c9 httputils: escape ampersand too 2017-06-05 10:10:58 -04:00
Adam b18d1a69b6 Merge pull request #174 from Techman-/2.0+inspsasl
InspIRCd: Send CHGIDENT/CHGHOST on SVSLOGIN
2017-05-27 12:29:12 -04:00
Adam 0ace685597 Merge pull request #188 from key2peace/2.0
IPv6 support for m_dnsbl and sockaddrs::reverse()
2017-05-27 09:58:34 -04:00
Alexander Maassen bfcfd0b727 Moved m_dns's reverse ip method to sockaddrs::reverse().
Updated m_dnsbl to support ipv6.
2017-05-27 09:56:18 -04:00
Adam 087f1cb359 m_dnsbl: fix exempts, allow cidrs, default exempt 127.0.0.0/8 2017-05-17 08:51:57 -04:00
Adam 010d20198e m_regex_posix: use REG_ICASE 2017-03-30 19:10:31 -04:00
Adam 953e804231 example.conf: disable regexengine directive by default 2017-03-30 17:02:36 -04:00
Adam c656fe0694 regchannel: fix compile warning from previous commit 2017-03-27 22:25:49 -04:00
Adam fb3ec7a897 cs_akick: don't show channel doesn't exist message in enforce from adding akicks 2017-03-27 21:41:35 -04:00
Adam 274658f955 Fix autokick destructor to properly remove channel references from accounts 2017-03-27 21:14:32 -04:00
Adam 7621306f4b example.conf: update to reflect deprecated status of older encryption modules 2017-03-26 18:34:03 -04:00
Adam b804867105 Remove weird warning in nickserv help which for some reason assumes admins' abuse policies 2017-03-23 20:05:09 -04:00
Adam f8f1550c31 Merge pull request #187 from miwob/new-mode
Add channel mode 'u', and 'L' to hybrid protocol module; Remove usele…
2017-03-19 18:56:06 -04:00
Adam 0fcc66711b m_sasl: pass module to logger 2017-03-19 18:55:32 -04:00
Adam 8d9574e306 readme: change minimum supported hybrid version to 8.2 2017-03-19 18:55:19 -04:00
miwob 6cb17c734c Add channel mode 'u', and 'L' to hybrid protocol module; Remove useless CAPABs that are mandatory for some years now. 2017-03-19 12:02:22 +01:00
Adam 3545e8e383 Fix ns_keep_modes default option in nickserv.conf 2017-03-18 15:30:17 -04:00
Adam 3c18e02b0b logger.cpp: fix variable shadow warning 2017-03-16 21:37:34 -04:00
Adam b831cd8a36 Include ip for web clients in command log messages for source 2017-03-16 20:23:57 -04:00
Adam 516ab164f6 redis: check for socket errors when loading database on startup 2017-03-16 20:13:56 -04:00
Adam b2d028533d cs_xop: fix showing alternative access methods in help 2017-03-15 21:44:05 -04:00
Adam a88d9cb1f0 modes.cpp: correct usage of format string passed to SendMode 2017-03-08 19:58:25 -05:00
Adam b57ef5d2c7 db_redis: don't crash if destroying an object with no type 2017-03-08 16:23:30 -05:00
Adam 1a96390826 unreal4: set +xt on chghost as unreal does 2017-03-01 17:44:05 -05:00
Adam 60339edf40 cs_set: don't lower ts from own clients joining 2017-02-21 14:44:33 -05:00
Adam 6990c692d6 Unwrap list modes too in cs_mode, and fix clear on virtual modes to show an error 2017-02-21 12:36:59 -05:00
Adam 98e62b4032 Fix logging in cs_mode set 2017-02-21 12:35:51 -05:00
Adam a1d7d42d6a Unwrap mode changes in RemoveMode before checking if it is set, fixes os_mode not being able to remove extbans etc 2017-02-21 12:35:20 -05:00
Adam 3f7c0829ef os_forbid: match forbids exact on add/del 2017-02-21 09:59:10 -05:00
Adam 46d8af781d Verify configured servername and uplink password are valid 2017-02-21 08:19:03 -05:00
Adam 67b7c8bd7d os_logsearch: fix quick match 2017-02-12 16:46:13 -05:00
Adam 21486e2c81 Merge pull request #185 from fallen/2.0
Update French language file
2017-02-06 14:20:40 -05:00
Adam 29ac40b584 ns_set_misc/cs_set_misc: send syntax help too 2017-02-06 14:06:55 -05:00
Adam dde444ed0e protocol/inspircd12: set +x on /hs off 2017-02-06 13:15:01 -05:00
Adam 9b6c209c80 bs_badwords: allow opers with botserv/administration to list/clear badwords too 2017-02-04 20:21:40 -05:00
Yann Sionneau 3c7d67c8cd Update French language file
- translate "nick" to "pseudo"
- remove "XOP" arg from set secureops
2017-02-04 23:47:05 +01:00
Adam c730291762 logger: some log events rely on empty sources 2017-01-23 08:03:51 -05:00
Adam c593661f40 Anope 2.0.6-git 2017-01-22 17:04:20 -05:00
Michael Hazell 3b62c8f3e2 InspIRCd: Send CHGIDENT/CHGHOST on SVSLOGIN 2016-09-25 14:50:03 -04:00
71 changed files with 1290 additions and 1316 deletions
+46
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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]
+1 -1
View File
@@ -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
+16
View File
@@ -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
+7
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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; }
+2
View File
@@ -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) */
+1
View File
@@ -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();
+6
View File
@@ -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,
+3
View File
@@ -228,6 +228,9 @@ namespace HTTPUtils
case '"':
dst += "&quot;";
break;
case '&':
dst += "&amp;";
break;
default:
dst += src[i];
}
+2
View File
@@ -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;
};
+2
View File
@@ -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;
+2 -2
View File
@@ -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";
}
};
}
+5
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+503 -602
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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;
+27 -15
View File
@@ -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> &params)
{
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> &params)
@@ -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)
+13 -3
View File
@@ -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> &params)
@@ -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");
+6 -63
View File
@@ -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;
+1
View File
@@ -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;
}
+1 -1
View File
@@ -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"
+27 -14
View File
@@ -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());
+1
View File
@@ -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;
}
+14 -2
View File
@@ -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)
+1 -1
View File
@@ -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)
{
-1
View File
@@ -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);
+25 -1
View File
@@ -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));
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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());
+2 -1
View File
@@ -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())
+5 -5
View File
@@ -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'));
+12 -6
View File
@@ -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;
+3 -2
View File
@@ -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
+17 -17
View File
@@ -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
+21 -19
View File
@@ -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);
}
}
}
-7
View File
@@ -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)
+7 -7
View File
@@ -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"))
+6 -6
View File
@@ -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);
+1 -1
View File
@@ -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";
+3 -3
View File
@@ -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);
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -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");
+1 -1
View File
@@ -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())
+33
View File
@@ -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));
+6 -1
View File
@@ -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;
};
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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");
+3 -3
View File
@@ -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"))
+2 -2
View File
@@ -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)
+5 -1
View File
@@ -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;
}
}
+9 -3
View File
@@ -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> &params, 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> &params, 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> &params, 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> &params, 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);
}
+3 -2
View File
@@ -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> &params, 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> &params, 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> &params, 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> &params, TemplateFileServer::Replacements &r, const Anope::string &key = "MESSAGES");
}
#include "pages/index.h"
+14 -9
View File
@@ -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 &param, 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 &para
}
/* 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 &para
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 &param, bool enforce_mlock)
+17 -3
View File
@@ -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())
{
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+35
View File
@@ -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
View File
@@ -2,5 +2,5 @@
VERSION_MAJOR=2
VERSION_MINOR=0
VERSION_PATCH=5
VERSION_PATCH=6
VERSION_EXTRA=""