1
0
mirror of https://github.com/anope/anope.git synced 2026-07-08 23:43:13 +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. * 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. * 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 * encrypted by this module. Old passwords stored in another encryption method are
* automatically re-encrypted by the primary encryption module on next identify. * 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 * enc_md5, enc_sha1, and enc_old are deprecated, and are provided for users
* versions prior to Anope 1.7.17. If your databases were made using that module, * to upgrade to a newer encryption module. Do not use them as the primary
* use this and not enc_md5. * encryption module. They will be removed in a future release.
*
* 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.
* *
*/ */
#module { name = "enc_bcrypt" } #module { name = "enc_bcrypt" }
module { name = "enc_sha256" } 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 * 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" } #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. * 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 * 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 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: * authenticating users through this mechanism. Supported mechanisms are:
* PLAIN, EXTERNAL. * PLAIN, EXTERNAL.
*/ */
#module { name = "m_sasl" } module { name = "m_sasl" }
/* /*
* m_ssl_gnutls [EXTRA] * 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 * - 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 * - msg: Services messages will be sent as PRIVMSGs instead of NOTICEs, requires
* options:useprivmsg to be enabled as well * 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. * - 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 * 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 Anope Version 2.0.5
------------------- -------------------
Fix negative levels to not match users with negative access 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 Anope Version 2.0.5
------------------- -------------------
No significant changes. No significant changes.
+2 -4
View File
@@ -9,8 +9,6 @@ This program is free but copyrighted software; see the file COPYING for
details. details.
Information about Anope may be found at http://www.anope.org/ 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 Table of Contents
----------------- -----------------
@@ -19,7 +17,7 @@ Table of Contents
3) Installation 3) Installation
4) Command Line Options 4) Command Line Options
5) Messages Translation 5) Messages Translation
6) Contact and Mailing List 6) Contact
1) Credits 1) Credits
@@ -170,7 +168,7 @@ Table of Contents
* Bahamut 1.4.27 or later (including 1.8) * Bahamut 1.4.27 or later (including 1.8)
* Charybdis 3.4 or later * Charybdis 3.4 or later
* Hybrid 8.1 or later * Hybrid 8.2 or later
* InspIRCd 1.2 or 2.0 * InspIRCd 1.2 or 2.0
* ngIRCd 19.2 or later * ngIRCd 19.2 or later
* Plexus 3 or later * Plexus 3 or later
+1
View File
@@ -246,6 +246,7 @@ class CoreExport IdentifyRequest
virtual void OnSuccess() = 0; virtual void OnSuccess() = 0;
virtual void OnFail() = 0; virtual void OnFail() = 0;
Module *GetOwner() const { return owner; }
const Anope::string &GetAccount() const { return account; } const Anope::string &GetAccount() const { return account; }
const Anope::string &GetPassword() const { return password; } const Anope::string &GetPassword() const { return password; }
+2
View File
@@ -59,6 +59,8 @@ class CoreExport CommandSource
public: public:
/* The account executing the command */ /* The account executing the command */
Reference<NickCore> nc; Reference<NickCore> nc;
/* for web clients */
Anope::string ip;
/* Where the reply should go */ /* Where the reply should go */
CommandReply *reply; CommandReply *reply;
/* Channel the command was executed on (fantasy) */ /* 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 &, bool);
~File(); ~File();
const Anope::string &GetName() const; const Anope::string &GetName() const;
Anope::string GetPath() const;
bool IsOpen() const; bool IsOpen() const;
bool Open(); bool Open();
+6
View File
@@ -301,6 +301,11 @@ class CoreExport Module : public Extensible
* before they will be called. * 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. /** Called before a user has been kicked from a channel.
* @param source The kicker * @param source The kicker
* @param cu The user, channel, and status of the user being kicked * @param cu The user, channel, and status of the user being kicked
@@ -1099,6 +1104,7 @@ class CoreExport Module : public Extensible
enum Implementation enum Implementation
{ {
I_OnPostInit,
I_OnPreUserKicked, I_OnUserKicked, I_OnReload, I_OnPreBotAssign, I_OnBotAssign, I_OnBotUnAssign, I_OnUserConnect, 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_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, I_OnLoadDatabase, I_OnEncrypt, I_OnDecrypt, I_OnBotFantasy, I_OnBotNoFantasyAccess, I_OnBotBan, I_OnBadWordAdd,
+3
View File
@@ -228,6 +228,9 @@ namespace HTTPUtils
case '"': case '"':
dst += "&quot;"; dst += "&quot;";
break; break;
case '&':
dst += "&amp;";
break;
default: default:
dst += src[i]; 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 *FindForbid(const Anope::string &mask, ForbidType type) = 0;
virtual ForbidData *FindForbidExact(const Anope::string &mask, ForbidType type) = 0;
virtual std::vector<ForbidData *> GetForbids() = 0; virtual std::vector<ForbidData *> GetForbids() = 0;
}; };
+2
View File
@@ -58,6 +58,8 @@ namespace Redis
public: public:
Provider(Module *c, const Anope::string &n) : Service(c, "Redis::Provider", n) { } 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 std::vector<Anope::string> &cmds) = 0;
virtual void SendCommand(Interface *i, const Anope::string &str) = 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()) if (!hostname.empty() && !ip.empty())
user = hostname + " (" + ip + ")"; 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); sasl->Succeed(s, na->nc);
delete s; delete s;
} }
@@ -133,7 +133,7 @@ namespace SASL
if (!hostname.empty() && !ip.empty()) if (!hostname.empty() && !ip.empty())
user = hostname + " (" + ip + ")"; 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; Anope::string addr() const;
/** Get the reverse address represented by this addr
* @return The reverse address
*/
Anope::string reverse() const;
/* Is this address ipv6? */ /* Is this address ipv6? */
bool ipv6() const; 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; 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); source.Reply(ACCESS_DENIED);
return; return;
+27 -15
View File
@@ -13,6 +13,31 @@
class CommandCSAKick : public Command 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) void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{ {
Anope::string mask = params[2]; 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()); 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) 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) void DoEnforce(CommandSource &source, ChannelInfo *ci)
{ {
Channel *c = ci->c; Channel *c = ci->c;
int count = 0;
if (!c) if (!c)
{ {
@@ -392,19 +416,7 @@ class CommandCSAKick : public Command
return; return;
} }
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) this->Enforce(source, ci);
{
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 DoClear(CommandSource &source, ChannelInfo *ci) void DoClear(CommandSource &source, ChannelInfo *ci)
+13 -3
View File
@@ -654,6 +654,10 @@ class CommandCSMode : public Command
break; break;
if (!sep.GetToken(param)) if (!sep.GetToken(param))
break; break;
// Change to internal name, eg giving -b ~q:*
cm = cm->Unwrap(param);
if (adding) if (adding)
{ {
if (IRCD->GetMaxListFor(ci->c) && ci->c->HasMode(cm->name) < IRCD->GetMaxListFor(ci->c)) 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]); ci->c->RemoveMode(NULL, cm, v[j]);
} }
} }
} } // switch
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to set " << params[2] << (params.size() > 3 ? " " + params[3] : "");
} }
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) void DoClear(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
@@ -709,6 +713,12 @@ class CommandCSMode : public Command
return; 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; std::vector<Anope::string> new_params;
new_params.push_back(params[0]); new_params.push_back(params[0]);
new_params.push_back("SET"); new_params.push_back("SET");
+6 -63
View File
@@ -504,20 +504,6 @@ class CommandCSSetPersist : public Command
{ {
ci->Extend<bool>("PERSIST"); 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 */ /* Set the perm mode */
if (cm) if (cm)
{ {
@@ -541,7 +527,7 @@ class CommandCSSetPersist : public Command
} }
ChanServ->Assign(NULL, ci); ChanServ->Assign(NULL, ci);
if (!ci->c->FindUser(ChanServ)) if (ci->c && !ci->c->FindUser(ChanServ))
{ {
ChannelStatus status(BotModes()); ChannelStatus status(BotModes());
ChanServ->Join(ci->c, &status); ChanServ->Join(ci->c, &status);
@@ -1099,7 +1085,8 @@ class CommandCSSetNoexpire : public Command
class CSSet : public Module class CSSet : public Module
{ {
SerializableExtensibleItem<bool> noautoop, peace, securefounder, SerializableExtensibleItem<bool> noautoop, peace, securefounder,
restricted, secure, secureops, signkick, signkick_level, noexpire; restricted, secure, secureops, signkick, signkick_level, noexpire,
persist;
struct KeepModes : SerializableExtensibleItem<bool> struct KeepModes : SerializableExtensibleItem<bool>
{ {
@@ -1147,51 +1134,6 @@ class CSSet : public Module
} }
} keep_modes; } 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; CommandCSSet commandcsset;
CommandCSSetAutoOp commandcssetautoop; CommandCSSetAutoOp commandcssetautoop;
CommandCSSetBanType commandcssetbantype; CommandCSSetBanType commandcssetbantype;
@@ -1218,7 +1160,8 @@ class CSSet : public Module
securefounder(this, "SECUREFOUNDER"), restricted(this, "RESTRICTED"), securefounder(this, "SECUREFOUNDER"), restricted(this, "RESTRICTED"),
secure(this, "CS_SECURE"), secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"), secure(this, "CS_SECURE"), secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"),
signkick_level(this, "SIGNKICK_LEVEL"), noexpire(this, "CS_NO_EXPIRE"), 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), commandcsset(this), commandcssetautoop(this), commandcssetbantype(this),
commandcssetdescription(this), commandcssetfounder(this), commandcssetkeepmodes(this), commandcssetdescription(this), commandcssetfounder(this), commandcssetkeepmodes(this),
@@ -1299,7 +1242,7 @@ class CSSet : public Module
void OnJoinChannel(User *u, Channel *c) anope_override 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; Log(LOG_DEBUG) << "Changing TS of " << c->name << " from " << c->creation_time << " to " << c->ci->time_registered;
c->creation_time = 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)) if (descriptions.count(source.command))
{ {
this->SendSyntax(source);
source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str())); source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str()));
return true; return true;
} }
+1 -1
View File
@@ -561,7 +561,7 @@ class CommandCSXOP : public Command
BotInfo *access_bi, *flags_bi; BotInfo *access_bi, *flags_bi;
Anope::string access_cmd, flags_cmd; Anope::string access_cmd, flags_cmd;
Command::FindCommandFromService("chanserv/access", access_bi, access_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()) if (!access_cmd.empty() || !flags_cmd.empty())
{ {
source.Reply(_("Alternative methods of modifying channel access lists are\n" 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 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; return;
User *u = source.GetUser();
NickAlias *na = NickAlias::Find(nick); NickAlias *na = NickAlias::Find(nick);
/* If the nick is already registered, drop it. */ /* If the nick is already registered, drop it. */
if (na) if (na)
{ {
FOREACH_MOD(OnChangeCoreDisplay, (na->nc, u->nick));
delete na; delete na;
} }
na = new NickAlias(nick, target->nc); 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; na->time_registered = na->last_seen = Anope::CurTime;
u->Login(target->nc); if (u != NULL)
FOREACH_MOD(OnNickGroup, (u, target)); {
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") << ")"; 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()); 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 void OnFail() anope_override
{ {
if (!source.GetUser()) User *u = source.GetUser();
return;
Log(LOG_COMMAND, source, cmd) << "and failed to group to " << target->nick; Log(LOG_COMMAND, source, cmd) << "and failed to group to " << target->nick;
if (NickAlias::Find(GetAccount()) != NULL) if (NickAlias::Find(GetAccount()) != NULL)
{ {
source.Reply(PASSWORD_INCORRECT); source.Reply(PASSWORD_INCORRECT);
source.GetUser()->BadPassword(); if (u)
u->BadPassword();
} }
else else
source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str()); 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)) if (descriptions.count(source.command))
{ {
this->SendSyntax(source);
source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str())); source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str()));
return true; return true;
} }
+14 -2
View File
@@ -105,6 +105,18 @@ class MyForbidService : public ForbidService
return NULL; 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 *> GetForbids() anope_override
{ {
std::vector<ForbidData *> f; std::vector<ForbidData *> f;
@@ -203,7 +215,7 @@ class CommandOSForbid : public Command
return; return;
} }
ForbidData *d = this->fs->FindForbid(entry, ftype); ForbidData *d = this->fs->FindForbidExact(entry, ftype);
bool created = false; bool created = false;
if (d == NULL) if (d == NULL)
{ {
@@ -322,7 +334,7 @@ class CommandOSForbid : public Command
{ {
const Anope::string &entry = params[2]; const Anope::string &entry = params[2];
ForbidData *d = this->fs->FindForbid(entry, ftype); ForbidData *d = this->fs->FindForbidExact(entry, ftype);
if (d != NULL) if (d != NULL)
{ {
if (Anope::ReadOnly) if (Anope::ReadOnly)
+1 -1
View File
@@ -113,7 +113,7 @@ class CommandOSLogSearch : public Command
else if (wildcard) else if (wildcard)
match = Anope::Match(buf, "*" + search_string + "*"); match = Anope::Match(buf, "*" + search_string + "*");
else else
match = buf.find_first_of_ci(search_string) != Anope::string::npos; match = buf.find_ci(search_string) != Anope::string::npos;
if (match) 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 = new MyOper(na->nc->display, ot);
na->nc->o->require_oper = true;
if (Anope::ReadOnly) if (Anope::ReadOnly)
source.Reply(READ_ONLY_MODE); source.Reply(READ_ONLY_MODE);
+25 -1
View File
@@ -179,6 +179,12 @@ class DatabaseRedis : public Module, public Pipe
EventReturn OnLoadDatabase() anope_override 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(); const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
for (unsigned i = 0; i < type_order.size(); ++i) for (unsigned i = 0; i < type_order.size(); ++i)
{ {
@@ -186,7 +192,13 @@ class DatabaseRedis : public Module, public Pipe
this->OnSerializeTypeCreate(sb); 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:*"); redis->Subscribe(&this->sl, "__keyspace@*__:hash:*");
@@ -215,6 +227,18 @@ class DatabaseRedis : public Module, public Pipe
{ {
Serialize::Type *t = obj->GetSerializableType(); 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; std::vector<Anope::string> args;
args.push_back("HGETALL"); args.push_back("HGETALL");
args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id)); args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
+1 -1
View File
@@ -17,7 +17,7 @@ class POSIXRegex : public Regex
public: public:
POSIXRegex(const Anope::string &expr) : Regex(expr) 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) if (err)
{ {
char buf[BUFSIZE]; char buf[BUFSIZE];
+9 -25
View File
@@ -296,32 +296,16 @@ class Packet : public Query
if (!ip.valid()) if (!ip.valid())
throw SocketException("Invalid IP"); throw SocketException("Invalid IP");
if (q.name.find(':') != Anope::string::npos) switch (ip.family())
{ {
const char *const hex = "0123456789abcdef"; case AF_INET6:
char reverse_ip[128]; q.name = ip.reverse() + ".ip6.arpa";
unsigned reverse_ip_count = 0; break;
for (int j = 15; j >= 0; --j) case AF_INET:
{ q.name = ip.reverse() + ".in-addr.arpa";
reverse_ip[reverse_ip_count++] = hex[ip.sa6.sin6_addr.s6_addr[j] & 0xF]; break;
reverse_ip[reverse_ip_count++] = '.'; default:
reverse_ip[reverse_ip_count++] = hex[ip.sa6.sin6_addr.s6_addr[j] >> 4]; throw SocketException("Unsupported IP Family");
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";
} }
} }
+15 -11
View File
@@ -99,7 +99,7 @@ class DNSBLResolver : public Request
class ModuleDNSBL : public Module class ModuleDNSBL : public Module
{ {
std::vector<Blacklist> blacklists; std::vector<Blacklist> blacklists;
std::set<Anope::string> exempts; std::set<cidr> exempts;
bool check_on_connect; bool check_on_connect;
bool check_on_netburst; bool check_on_netburst;
bool add_to_akill; bool add_to_akill;
@@ -146,7 +146,10 @@ class ModuleDNSBL : public Module
this->exempts.clear(); this->exempts.clear();
for (int i = 0; i < block->CountBlock("exempt"); ++i) 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 void OnUserConnect(User *user, bool &exempt) anope_override
@@ -157,25 +160,26 @@ class ModuleDNSBL : public Module
if (!this->check_on_netburst && !user->server->IsSynced()) if (!this->check_on_netburst && !user->server->IsSynced())
return; return;
/* At this time we only support IPv4 */ if (!user->ip.valid())
if (!user->ip.valid() || user->ip.sa.sa_family != AF_INET) /* User doesn't have a valid IP (spoof/etc) */
/* User doesn't have a valid IPv4 IP (ipv6/spoof/etc) */ return;
if (this->blacklists.empty())
return; return;
if (this->exempts.count(user->ip.addr())) if (this->exempts.count(user->ip.addr()))
{
Log(LOG_DEBUG) << "User " << user->nick << " is exempt from dnsbl check - ip: " << user->ip.addr();
return; return;
}
const unsigned long &ip = user->ip.sa4.sin_addr.s_addr; Anope::string reverse = user->ip.reverse();
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;
for (unsigned i = 0; i < this->blacklists.size(); ++i) for (unsigned i = 0; i < this->blacklists.size(); ++i)
{ {
const Blacklist &b = this->blacklists[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; DNSBLResolver *res = NULL;
try try
{ {
+9 -2
View File
@@ -157,6 +157,11 @@ class MyRedisService : public Provider
} }
public: 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) void SendCommand(RedisSocket *s, Interface *i, const std::vector<Anope::string> &cmds)
{ {
std::vector<std::pair<const char *, size_t> > args; std::vector<std::pair<const char *, size_t> > args;
@@ -201,9 +206,11 @@ class MyRedisService : public Provider
public: public:
bool BlockAndProcess() anope_override bool BlockAndProcess() anope_override
{ {
this->sock->ProcessWrite(); if (!this->sock->ProcessWrite())
this->sock->flags[SF_DEAD] = true;
this->sock->SetBlocking(true); this->sock->SetBlocking(true);
this->sock->ProcessRead(); if (!this->sock->ProcessRead())
this->sock->flags[SF_DEAD] = true;
this->sock->SetBlocking(false); this->sock->SetBlocking(false);
return !this->sock->interfaces.empty(); return !this->sock->interfaces.empty();
} }
+2 -2
View File
@@ -111,13 +111,13 @@ class External : public Mechanism
NickCore *nc = certs->FindAccountFromCert(mysess->cert); NickCore *nc = certs->FindAccountFromCert(mysess->cert);
if (!nc || nc->HasExt("NS_SUSPENDED") || nc->HasExt("UNCONFIRMED")) 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); sasl->Fail(sess);
delete sess; delete sess;
return; 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); sasl->Succeed(sess, nc);
delete sess; delete sess;
} }
+15 -14
View File
@@ -107,7 +107,7 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
prev = cur; prev = cur;
cur.clear(); cur.clear();
int len = 0; size_t len = 0;
istag = false; istag = false;
if (content[0] == '<') if (content[0] == '<')
@@ -120,20 +120,21 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
len = content.find_first_of('<'); 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);
cur = content.substr(1, len - 1); while (!content.empty() && content[0] == ' ')
content.erase(0, len + 1); content.erase(content.begin());
while (!content.empty() && content[0] == ' ') }
content.erase(content.begin()); else
} {
else cur = content.substr(0, len);
{ content.erase(0, len);
cur = content.substr(0,len);
content.erase(0, len);
}
} }
} }
while (istag && !content.empty()); while (istag && !content.empty());
+2 -1
View File
@@ -108,7 +108,8 @@ class MyXMLRPCEvent : public XMLRPCEvent
} }
reply(out); 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); Command::Run(source, command);
if (!out.empty()) if (!out.empty())
+5 -5
View File
@@ -1,7 +1,7 @@
/* ircd-hybrid-8 protocol module /* ircd-hybrid-8 protocol module
* *
* (C) 2003-2017 Anope Team <team@anope.org> * (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. * 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(); 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: * which are required to work with IRC-services:
* *
* QS - Can handle quit storm removal * QS - Can handle quit storm removal
* EX - Can do channel +e exemptions
* IE - Can do invite exceptions
* CHW - Can do channel wall @# * CHW - Can do channel wall @#
* TBURST - Supports topic burst * TBURST - Supports topic burst
* ENCAP - Supports ENCAP * ENCAP - Supports ENCAP
@@ -197,7 +195,7 @@ class HybridProto : public IRCDProto
* SVS - Supports services * SVS - Supports services
* EOB - Supports End Of Burst message * 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); SendServer(Me);
@@ -662,7 +660,9 @@ class ProtoHybrid : public Module
ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r')); ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r'));
ModeManager::AddChannelMode(new ChannelMode("SECRET", 's')); ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't')); ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
ModeManager::AddChannelMode(new ChannelMode("HIDEBMASKS", 'u'));
ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C')); ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
ModeManager::AddChannelMode(new ChannelModeOperOnly("LBAN", 'L'));
ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M')); ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M'));
ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O')); ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O'));
ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R')); ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
+12 -6
View File
@@ -151,13 +151,14 @@ class InspIRCd12Proto : public IRCDProto
void SendVhostDel(User *u) anope_override void SendVhostDel(User *u) anope_override
{ {
if (u->HasMode("CLOAK")) UserMode *um = ModeManager::FindUserModeByName("CLOAK");
this->SendChgHostInternal(u->nick, u->chost);
else
this->SendChgHostInternal(u->nick, u->host);
if (Servers::Capab.count("CHGIDENT") && u->GetIdent() != u->GetVIdent()) if (um && !u->HasMode(um->name))
this->SendChgIdentInternal(u->nick, u->GetIdent()); // 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 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 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; 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; SASLUser su;
su.uid = uid; 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)); 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)); 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 void SendSVSNOOP(const Server *server, bool set) anope_override
+17 -17
View File
@@ -158,7 +158,8 @@ class UnrealIRCdProto : public IRCDProto
/* JOIN */ /* JOIN */
void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override 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) if (status)
{ {
/* First save the channel status incase uc->Status == 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; UplinkSocket::Message(Me) << "CHGIDENT " << u->GetUID() << " " << vIdent;
if (!vhost.empty()) if (!vhost.empty())
UplinkSocket::Message(Me) << "CHGHOST " << u->GetUID() << " " << vhost; 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 void SendConnect() anope_override
@@ -227,6 +232,15 @@ class UnrealIRCdProto : public IRCDProto
SendServer(Me); 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 */ /* SVSHOLD - set */
void SendSVSHold(const Anope::string &nick, time_t t) anope_override 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 void SendChannel(Channel *c) anope_override
{ {
/* Unreal does not support updating a channels TS without actually joining a user, UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name
* so we will join and part us now << " +" << c->GetModes(true, true) << " :";
*/
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);
}
} }
void SendSASLMessage(const SASL::Message &message) anope_override 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; return EVENT_CONTINUE;
} }
void OnPreUplinkSync(Server *serv) anope_override void OnPostInit() anope_override
{ {
if (!persist) if (!persist)
return; return;
ChannelMode *perm = ModeManager::FindChannelModeByName("PERM");
/* Find all persistent channels and create them, as we are about to finish burst to our uplink */ /* 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) for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
{ {
ChannelInfo *ci = it->second; ChannelInfo *ci = it->second;
if (persist->HasExt(ci)) if (!persist->HasExt(ci))
{ continue;
bool c;
ci->c = Channel::FindOrCreate(ci->name, c, ci->time_registered);
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) ChannelStatus status(BotModes());
IRCD->SendChannel(ci->c); ci->bi->Join(ci->c, &status);
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);
}
} }
} }
} }
-7
View File
@@ -493,13 +493,6 @@ class NickServCore : public Module, public NickServService
"Accounts that are not used anymore are subject to\n" "Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n" "the automatic expiration, i.e. they will be deleted\n"
"after %d days if not used."), nickserv_expire / 86400); "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) 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("DEL");
params.push_back(message.get_data["mask"]); 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) 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["mask"]);
params.push_back(message.post_data["access"]); 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") 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("ADD");
params.push_back(message.post_data["mask"]); 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") 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["mask"]);
params.push_back(message.post_data["access"]); 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); ChanAccess *access = ci->GetAccess(i);
replacements["MASKS"] = HTTPUtils::Escape(access->Mask()); replacements["MASKS"] = access->Mask();
replacements["ACCESSES"] = HTTPUtils::Escape(access->AccessSerialize()); replacements["ACCESSES"] = access->AccessSerialize();
replacements["CREATORS"] = HTTPUtils::Escape(access->creator); replacements["CREATORS"] = access->creator;
} }
if (Service::FindService("Command", "chanserv/access")) 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("DEL");
params.push_back(message.get_data["mask"]); 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) 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) if (message.post_data["reason"].empty() == false)
params.push_back(message.post_data["reason"]); 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); 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); AutoKick *akick = ci->GetAkick(i);
if (akick->nc) if (akick->nc)
replacements["MASKS"] = HTTPUtils::Escape(akick->nc->display); replacements["MASKS"] = akick->nc->display;
else else
replacements["MASKS"] = HTTPUtils::Escape(akick->mask); replacements["MASKS"] = akick->mask;
replacements["CREATORS"] = HTTPUtils::Escape(akick->creator); replacements["CREATORS"] = akick->creator;
replacements["REASONS"] = HTTPUtils::Escape(akick->reason); replacements["REASONS"] = akick->reason;
} }
Page.Serve(server, page_name, client, message, reply, replacements); 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);
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 else
replacements["MESSAGES"] = "Invalid Confirmation"; 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("SET");
params.push_back("-" + Anope::string(cm->mchar)); params.push_back("-" + Anope::string(cm->mchar));
params.push_back(message.get_data["mask"]); 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) 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("SET");
params.push_back("+" + Anope::string(cm->mchar)); params.push_back("+" + Anope::string(cm->mchar));
params.push_back(message.post_data["mask"]); 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); std::vector<Anope::string> v = c->GetModeList(cm->name);
for (unsigned int i = 0; i < v.size(); ++i) 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); 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); replacements["CHANNEL_ESCAPED"] = HTTPUtils::URLEncode(ci->name);
if (ci->GetFounder()) if (ci->GetFounder())
replacements["FOUNDER"] = ci->GetFounder()->display; replacements["FOUNDER"] = ci->GetFounder()->display;
@@ -114,8 +114,8 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
if (!ci->last_topic.empty()) if (!ci->last_topic.empty())
{ {
replacements["LAST_TOPIC"] = HTTPUtils::Escape(ci->last_topic); replacements["LAST_TOPIC"] = ci->last_topic;
replacements["LAST_TOPIC_SETTER"] = HTTPUtils::Escape(ci->last_topic_setter); replacements["LAST_TOPIC_SETTER"] = ci->last_topic_setter;
} }
if (can_set) if (can_set)
+1 -1
View File
@@ -21,7 +21,7 @@ bool WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &pa
if (!email.empty()) if (!email.empty())
params.push_back(email); 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"); 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; std::vector<Anope::string> params;
params.push_back(HTTPUtils::URLDecode(message.post_data["req"])); 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()) if (na->HasVhost())
+33
View File
@@ -36,6 +36,14 @@ class WebpanelRequest : public IdentifyRequest
return; 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; Anope::string id;
for (int i = 0; i < 64; ++i) 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_id", id);
na->Extend<Anope::string>("webcpanel_ip", client->GetIP()); na->Extend<Anope::string>("webcpanel_ip", client->GetIP());
na->nc->Extend<time_t>("webcpanel_last_login", Anope::CurTime);
{ {
HTTPReply::cookie c; HTTPReply::cookie c;
@@ -91,6 +100,30 @@ bool WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page
if (!user.empty() && !pass.empty()) if (!user.empty() && !pass.empty())
{ {
// Rate limit check. // 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); WebpanelRequest *req = new WebpanelRequest(me, reply, message, server, page_name, client, replacements, user, pass);
FOREACH_MOD(OnCheckAuthentication, (NULL, req)); FOREACH_MOD(OnCheckAuthentication, (NULL, req));
+6 -1
View File
@@ -12,8 +12,13 @@ namespace WebCPanel
class Index : public WebPanelPage class Index : public WebPanelPage
{ {
static const int FLUSH_TIME = 60;
Anope::hash_map<time_t> last_login_attempt;
time_t last_clear;
public: 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; 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["receiver"]));
params.push_back(HTTPUtils::URLDecode(message.post_data["message"])); 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) 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(chname);
params.push_back(message.get_data["number"]); 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) 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["NUMBER"] = stringify(i+1);
replacements["SENDER"] = m->sender; replacements["SENDER"] = m->sender;
replacements["TIME"] = Anope::strftime(m->time); replacements["TIME"] = Anope::strftime(m->time);
replacements["TEXT"] = HTTPUtils::Escape(m->text); replacements["TEXT"] = m->text;
if (m->unread) if (m->unread)
replacements["UNREAD"] = "YES"; replacements["UNREAD"] = "YES";
else 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("ADD");
params.push_back(message.post_data["access"]); 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) 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("DEL");
params.push_back(message.get_data["mask"]); 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) 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("ADD");
params.push_back(message.post_data["certfp"]); 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) 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("DEL");
params.push_back(message.get_data["mask"]); 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"); 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) 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); replacements["TIME_REGISTERED"] = Anope::strftime(na->time_registered, na->nc);
if (na->HasVhost()) 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"); Anope::string *greet = na->nc->GetExt<Anope::string>("greet");
if (greet) if (greet)
replacements["GREET"] = HTTPUtils::Escape(*greet); replacements["GREET"] = *greet;
if (na->nc->HasExt("AUTOOP")) if (na->nc->HasExt("AUTOOP"))
replacements["AUTOOP"]; replacements["AUTOOP"];
if (na->nc->HasExt("NS_PRIVATE")) 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["mask"]);
cmdstr << " " << HTTPUtils::URLDecode(message.post_data["reason"]); cmdstr << " " << HTTPUtils::URLDecode(message.post_data["reason"]);
params.push_back(cmdstr.str()); 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) 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; std::vector<Anope::string> params;
params.push_back("DEL"); params.push_back("DEL");
params.push_back(HTTPUtils::URLDecode(message.get_data["number"])); 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) 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) 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; finished += replacement;
} }
} }
+9 -3
View File
@@ -15,6 +15,7 @@ class ModuleWebCPanel : public Module
ServiceReference<HTTPProvider> provider; ServiceReference<HTTPProvider> provider;
Panel panel; Panel panel;
PrimitiveExtensibleItem<Anope::string> id, ip; PrimitiveExtensibleItem<Anope::string> id, ip;
PrimitiveExtensibleItem<time_t> last_login;
StaticFileServer style_css, logo_png, cubes_png, favicon_ico; StaticFileServer style_css, logo_png, cubes_png, favicon_ico;
@@ -44,7 +45,8 @@ class ModuleWebCPanel : public Module
public: public:
ModuleWebCPanel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), 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"), 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"), 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"), 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 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); ServiceReference<Command> cmd("Command", c);
if (!cmd) if (!cmd)
@@ -266,12 +268,15 @@ namespace WebPanel
my_reply(r, key); my_reply(r, key);
CommandSource source(user, NULL, nc, &my_reply, bi); CommandSource source(user, NULL, nc, &my_reply, bi);
source.ip = client->clientaddr.addr();
CommandInfo info; CommandInfo info;
info.name = c; info.name = c;
cmd->Run(source, "", info, params); 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); ServiceReference<Command> cmd("Command", c);
if (!cmd) if (!cmd)
@@ -303,6 +308,7 @@ namespace WebPanel
my_reply(r, key); my_reply(r, key);
CommandSource source(nc->display, NULL, nc, &my_reply, bi); CommandSource source(nc->display, NULL, nc, &my_reply, bi);
source.ip = client->clientaddr.addr();
cmd->Run(source, cmdname, *info, params); cmd->Run(source, cmdname, *info, params);
} }
+3 -2
View File
@@ -143,6 +143,7 @@ class WebPanelProtectedPage : public WebPanelPage
namespace WebPanel namespace WebPanel
{ {
/** Run a command /** 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 User name to run command as, probably nc->display unless nc == NULL
* @param nc Nick core to run command from * @param nc Nick core to run command from
* @param service Service for source.owner and source.service * @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 r Replacements, reply from command goes back here into key
* @param key The key to put the replies into r * @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" #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); 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) if (!cm)
return; return;
/* Don't unset modes that arent set */ /* Don't unset modes that arent set */
if ((cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && !HasMode(cm->name)) if ((cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && !HasMode(cm->name))
return; 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 */ /* Don't unset status that aren't set */
else if (cm->type == MODE_STATUS) if (cm->type == MODE_STATUS)
{ {
User *u = User::Find(param); User *u = User::Find(param);
if (!u || !HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm))) 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 */ /* Get the param to send, if we need it */
Anope::string realparam = param;
if (cm->type == MODE_PARAM) if (cm->type == MODE_PARAM)
{ {
realparam.clear(); param.clear();
ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm); ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
if (!cmp->minus_no_arg) if (!cmp->minus_no_arg)
this->GetParam(cmp->name, realparam); this->GetParam(cmp->name, param);
} }
if (Me->IsSynced()) if (Me->IsSynced())
@@ -505,12 +510,12 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &para
this->chanserv_modecount++; this->chanserv_modecount++;
} }
Anope::string wparam = realparam; /* Wrap to get ircd representation */
ChannelMode *wcm = cm->Wrap(wparam); ChannelMode *wcm = cm->Wrap(param);
ModeManager::StackerAdd(bi, this, wcm, false, wparam); ModeManager::StackerAdd(bi, this, wcm, false, param);
MessageSource ms(bi); 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) 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"), Block *serverinfo = this->GetBlock("serverinfo"), *options = this->GetBlock("options"),
*mail = this->GetBlock("mail"), *networkinfo = this->GetBlock("networkinfo"); *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", "description", serverinfo->Get<const Anope::string>("description"));
ValidateNotEmpty("serverinfo", "pid", serverinfo->Get<const Anope::string>("pid")); ValidateNotEmpty("serverinfo", "pid", serverinfo->Get<const Anope::string>("pid"));
ValidateNotEmpty("serverinfo", "motd", serverinfo->Get<const Anope::string>("motd")); ValidateNotEmpty("serverinfo", "motd", serverinfo->Get<const Anope::string>("motd"));
@@ -205,6 +211,9 @@ Conf::Conf() : Block("")
ValidateNotZero("uplink", "port", port); ValidateNotZero("uplink", "port", port);
ValidateNotEmpty("uplink", "password", password); 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)); this->Uplinks.push_back(Uplink(host, port, password, ipv6));
} }
@@ -656,6 +665,11 @@ const Anope::string &File::GetName() const
return this->name; return this->name;
} }
Anope::string File::GetPath() const
{
return (this->executable ? "" : Anope::ConfigDir + "/") + this->name;
}
bool File::IsOpen() const bool File::IsOpen() const
{ {
return this->fp != NULL; return this->fp != NULL;
@@ -713,14 +727,14 @@ void Conf::LoadConf(File &file)
return; return;
if (!file.Open()) 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; Anope::string itemname, wordbuffer;
std::stack<Block *> block_stack; std::stack<Block *> block_stack;
int linenumber = 0; int linenumber = 0;
bool in_word = false, in_quote = false, in_comment = false; 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... // Start reading characters...
while (!file.End()) while (!file.End())
{ {
+2
View File
@@ -553,6 +553,8 @@ void Anope::Init(int ac, char **av)
static_cast<void>(MOD_RESULT); static_cast<void>(MOD_RESULT);
Log() << "Databases loaded"; Log() << "Databases loaded";
FOREACH_MOD(OnPostInit, ());
for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
it->second->Sync(); it->second->Sync();
+7 -2
View File
@@ -146,8 +146,13 @@ Anope::string Log::FormatSource() const
else if (nc) else if (nc)
return nc->display; return nc->display;
else if (source) 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 Anope::string Log::FormatCommand() const
+3 -3
View File
@@ -647,7 +647,7 @@ void ModeManager::ProcessModes()
std::list<Anope::string> ModeStrings = BuildModeStrings(s); std::list<Anope::string> ModeStrings = BuildModeStrings(s);
for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit) 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; delete it->second;
} }
UserStackerObjects.clear(); UserStackerObjects.clear();
@@ -662,7 +662,7 @@ void ModeManager::ProcessModes()
std::list<Anope::string> ModeStrings = BuildModeStrings(s); std::list<Anope::string> ModeStrings = BuildModeStrings(s);
for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit) 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; delete it->second;
} }
ChannelStackerObjects.clear(); ChannelStackerObjects.clear();
@@ -678,7 +678,7 @@ static void StackerDel(std::map<T *, StackerInfo *> &map, T *obj)
StackerInfo *si = it->second; StackerInfo *si = it->second;
std::list<Anope::string> ModeStrings = BuildModeStrings(si); std::list<Anope::string> ModeStrings = BuildModeStrings(si);
for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit) 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; delete si;
map.erase(it); map.erase(it);
+2 -2
View File
@@ -50,10 +50,10 @@ NickAlias::NickAlias(const Anope::string &nickname, NickCore* nickcore) : Serial
NickAlias::~NickAlias() NickAlias::~NickAlias()
{ {
UnsetExtensibles();
FOREACH_MOD(OnDelNick, (this)); FOREACH_MOD(OnDelNick, (this));
UnsetExtensibles();
/* Accept nicks that have no core, because of database load functions */ /* Accept nicks that have no core, because of database load functions */
if (this->nc) if (this->nc)
{ {
+2 -2
View File
@@ -37,10 +37,10 @@ NickCore::NickCore(const Anope::string &coredisplay) : Serializable("NickCore"),
NickCore::~NickCore() NickCore::~NickCore()
{ {
UnsetExtensibles();
FOREACH_MOD(OnDelCore, (this)); FOREACH_MOD(OnDelCore, (this));
UnsetExtensibles();
if (!this->chanaccess->empty()) if (!this->chanaccess->empty())
Log(LOG_DEBUG) << "Non-empty chanaccess list in destructor!"; Log(LOG_DEBUG) << "Non-empty chanaccess list in destructor!";
+1 -1
View File
@@ -13,7 +13,7 @@
std::vector<Oper *> Oper::opers; 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); opers.push_back(this);
} }
+4 -5
View File
@@ -33,9 +33,8 @@ AutoKick::~AutoKick()
if (it != this->ci->akick->end()) if (it != this->ci->akick->end())
this->ci->akick->erase(it); this->ci->akick->erase(it);
const NickAlias *na = NickAlias::Find(this->mask); if (nc)
if (na != NULL) nc->RemoveChannelReference(this->ci);
na->nc->RemoveChannelReference(this->ci);
} }
} }
@@ -141,10 +140,10 @@ ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"),
ChannelInfo::~ChannelInfo() ChannelInfo::~ChannelInfo()
{ {
UnsetExtensibles();
FOREACH_MOD(OnDelChan, (this)); FOREACH_MOD(OnDelChan, (this));
UnsetExtensibles();
Log(LOG_DEBUG) << "Deleting channel " << this->name; Log(LOG_DEBUG) << "Deleting channel " << this->name;
if (this->c) if (this->c)
+35
View File
@@ -95,6 +95,41 @@ Anope::string sockaddrs::addr() const
return ""; 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 bool sockaddrs::ipv6() const
{ {
return sa.sa_family == AF_INET6; return sa.sa_family == AF_INET6;
+1 -1
View File
@@ -2,5 +2,5 @@
VERSION_MAJOR=2 VERSION_MAJOR=2
VERSION_MINOR=0 VERSION_MINOR=0
VERSION_PATCH=5 VERSION_PATCH=6
VERSION_EXTRA="" VERSION_EXTRA=""