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

Compare commits

..

38 Commits

Author SHA1 Message Date
Sadie Powell f3c94e5d23 Release 2.1.10. 2024-11-01 09:48:52 +00:00
Sadie Powell f2ab092742 Merge branch '2.0' into 2.1. 2024-10-27 16:14:09 +00:00
Sadie Powell 7d5ca5c90b Switch the city version of geoipupdate to a non-corrupt database.
Closes #439.
2024-10-27 16:13:51 +00:00
Sadie Powell 8ee85efd70 Fix parsing mode changes from users on UnrealIRCd. 2024-10-25 14:50:04 +01:00
Sadie Powell 0cab675825 Fix a typo in the change log. 2024-10-22 16:53:21 +01:00
Sadie Powell f1751dcb21 Replace usestrictprivmsg with something actually useful.
Every IRC server we support (other than Bahamut which is probably
on the chopping bock) uses UIDs so this setting does nothing.

Instead, allow configuring a server-side alias for each service
and use that when servicealias is enabled.
2024-10-22 16:29:22 +01:00
Sadie Powell 8b02613549 Fix some stuff that was missed in commit b94c3740b9. 2024-10-22 14:59:18 +01:00
Sadie Powell c9625ccf3f Update the change logs. 2024-10-22 14:41:52 +01:00
Sadie Powell 435ce51196 Move nickserv/set/message to a new module, kill options:useprivmsg. 2024-10-22 14:27:30 +01:00
TehPeGaSuS 57ac7cb4db Update the cron file name.
name
2024-10-20 23:53:23 +01:00
Sadie Powell 8cb2b801e9 Use the target nick as the default desc for mask access entries. 2024-10-19 17:40:24 +01:00
Sadie Powell 66b45534a8 Deduplicate the access code in cs_statusupdate. 2024-10-19 12:17:33 +01:00
Sadie Powell 499077826c Replace the Facebook ns_set_misc example with a non-URL alternative.
This makes it more clear you can use this for more than just an
URL to an external service.
2024-10-18 18:54:22 +01:00
Sadie Powell bc4d34ebd8 Merge branch '2.0' into 2.1 2024-10-18 11:50:54 +01:00
Sadie Powell f40719787f Fix a change that was missing from the previous commit. 2024-10-18 11:45:19 +01:00
Sadie Powell 934a13c21f Merge branch '2.0' into 2.1. 2024-10-18 11:41:53 +01:00
Sadie Powell e5602f956d Fix marking channels as persistent on InspIRCd and UnrealIRCd. 2024-10-18 11:26:03 +01:00
Sadie Powell de11a19e03 Updated the supported versions in the README. 2024-10-17 16:00:43 +01:00
Sadie Powell b437468b84 Add support for name-only extbans on InspIRCd. 2024-10-16 13:06:47 +01:00
Sadie Powell 0a99571c0f Merge branch '2.0' into 2.1. 2024-10-13 17:17:34 +01:00
Sadie Powell e704fa6266 Update the IRC server to point to Teranova. 2024-10-13 17:15:26 +01:00
Sadie Powell f908514095 Zero errno before calling popen. 2024-10-12 17:54:36 +01:00
Sadie Powell bafcba023c Switch geoipupdate.sh to use a mirror as the original data is gone. 2024-10-12 12:01:00 +01:00
Sadie Powell 9a44b74186 Let the user know about their cert being auto-added to their account. 2024-10-11 18:55:22 +01:00
Sadie Powell 883935c3e0 Merge branch '2.0' into 2.1. 2024-10-11 16:55:36 +01:00
Sadie Powell 6d34054b78 Change the mode lock before removing/adding the PERM mode.
This fixes being unable to unset mlock on the first attempt.
2024-10-11 15:45:02 +01:00
Sadie Powell 3da9b6df0d Fix matching stacked extbans. 2024-10-04 19:04:31 +01:00
Sadie Powell 0ab0e4737c Remove some unnecessary debug logging. 2024-10-04 15:08:44 +01:00
Sadie Powell cdf356ed33 Fix validating named extbans on UnrealIRCd. 2024-10-04 14:57:09 +01:00
Sadie Powell 7d268bb4ca Implement NEXTBANS support on UnrealIRCd.
Closes #431.
2024-10-04 13:25:44 +01:00
Sadie Powell 184350ff4a Fix extracting the mode parameters from MODE on UnrealIRCd. 2024-10-04 13:25:10 +01:00
Sadie Powell 4cdbf560e1 Fix matching extended bans in services.
Extended bans are stored without their prefix. Therefore, we should
not try to strip their prefix before matching.

Closes #288.

Co-authored-by: k4be <k4be@pirc.pl>
2024-10-04 13:01:29 +01:00
Sadie Powell cbccc79d37 Fix parsing extbans on InspIRCd v4. 2024-10-04 11:40:40 +01:00
Sadie Powell 9b188a6c04 Respect EXTBANFORMAT on InspIRCd v4. 2024-10-04 11:20:19 +01:00
Sadie Powell 2f74513246 Change User::SetModesInternal to take a split mode change. 2024-10-02 23:54:36 +01:00
Sadie Powell 94dbb19593 Remove the formatting overload of User::SetModesInternal. 2024-10-02 11:15:42 +01:00
Sadie Powell 8232759a92 Change Channel::SetModesInternal to take a split mode change. 2024-10-02 11:12:24 +01:00
Sadie Powell b006966d25 Bump for 2.1.10-git. 2024-10-01 11:47:23 +01:00
64 changed files with 748 additions and 647 deletions
+1 -1
View File
@@ -14,6 +14,6 @@ Version | Supported
## Reporting a Vulnerability
Please do not report security vulnerabilities on GitHub. Instead, email the details to team@anope.org or get the attention of a developer in our development IRC channel at irc.anope.org #anope-devel and PM them the details.
Please do not report security vulnerabilities on GitHub. Instead, email the details to team@anope.org or get the attention of a developer in our development IRC channel at irc.teranova.net #anope-devel and PM them the details.
We will triage your issue as soon as possible and try to release a fixed version within a week of receiving your report.
+2 -2
View File
@@ -4,7 +4,7 @@ Anope is an open source set of IRC services. It is highly modular, with a vast n
* [Website](https://anope.org)
* [GitHub](https://github.com/anope)
* IRC \#anope on irc.anope.org
* IRC \#anope on irc.teranova.net
## Installation
@@ -33,7 +33,7 @@ Copy conf/anope.example.conf to conf/anope.conf
$ cp conf/anope.example.conf conf/anope.conf
```
Edit anope.conf, configuring the uplink, serverinfo, and protocol module configurations. Example link blocks for popular IRCds are included in the anope.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).
Edit anope.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.teranova.net](ircs://irc.teranova.net/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 `anope.conf` to include the new file.
+1 -1
View File
@@ -1,4 +1,4 @@
# Only install example.chk and anope.example.conf from this directory
# Only install cron.example.sh and anope.example.conf from this directory
# NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file)
set(DATA cron.example.sh anope.example.conf botserv.example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf chanstats.example.conf irc2sql.example.conf stats.standalone.example.conf)
install(FILES ${DATA}
+4 -19
View File
@@ -430,26 +430,11 @@ options
timeoutcheck = 3s
/*
* If set, this will allow users to let services send PRIVMSGs to them
* instead of NOTICEs. Also see the "msg" option of nickserv:defaults,
* which also toggles the default communication (PRIVMSG or NOTICE) to
* use for unregistered users.
*
* This is a feature that is against the IRC RFC and should be used ONLY
* if absolutely necessary.
*
* This directive is optional, and not recommended.
* If set Anope will tell users to use a server-side alias for messaging
* services instead of /msg. The alias for each service defaults to the
* bot name but can be configured in the service block.
*/
#useprivmsg = yes
/*
* If set, will force services to only respond to PRIVMSGs addresses to
* Nick@ServerName - e.g. NickServ@example.com. This should be used in
* conjunction with IRCd aliases. This directive is optional.
*
* This option will have no effect on some IRCds, such as TS6 IRCds.
*/
#usestrictprivmsg = yes
#servicealias = yes
/*
* If set, Anope will only show /stats o to IRC Operators. This directive
+13 -2
View File
@@ -59,6 +59,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
/*
* The server alias that can be used to securely message this service. If
* your IRC server does not have an alias for this service you can set this
* to an empty string to tell users to use /msg instead.
*
* This setting is ignored when options:servicealias is disabled.
*
* Defaults to the nick of the service if not set.
*/
#alias = "BS"
}
/*
@@ -334,10 +345,10 @@ privilege
/*
* fantasy
*
* Allows 'fantasist' commands to be used in channels.
* Allows fantasy commands (e.g. !kick) to be used in channels.
*
* Provides the commands:
* botserv/set/fantasy - Used for enabling or disabling BotServ's fantasist commands.
* botserv/set/fantasy - Used for enabling or disabling BotServ's fantasy commands.
*/
module
{
+11
View File
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
/*
* The server alias that can be used to securely message this service. If
* your IRC server does not have an alias for this service you can set this
* to an empty string to tell users to use /msg instead.
*
* This setting is ignored when options:servicealias is disabled.
*
* Defaults to the nick of the service if not set.
*/
#alias = "CS"
}
/*
+11
View File
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
/*
* The server alias that can be used to securely message this service. If
* your IRC server does not have an alias for this service you can set this
* to an empty string to tell users to use /msg instead.
*
* This setting is ignored when options:servicealias is disabled.
*
* Defaults to the nick of the service if not set.
*/
#alias = "GL"
}
/*
+11
View File
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
/*
* The server alias that can be used to securely message this service. If
* your IRC server does not have an alias for this service you can set this
* to an empty string to tell users to use /msg instead.
*
* This setting is ignored when options:servicealias is disabled.
*
* Defaults to the nick of the service if not set.
*/
#alias = "HS"
}
/*
+11
View File
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
/*
* The server alias that can be used to securely message this service. If
* your IRC server does not have an alias for this service you can set this
* to an empty string to tell users to use /msg instead.
*
* This setting is ignored when options:servicealias is disabled.
*
* Defaults to the nick of the service if not set.
*/
#alias = "MS"
}
/*
+29 -8
View File
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
/*
* The server alias that can be used to securely message this service. If
* your IRC server does not have an alias for this service you can set this
* to an empty string to tell users to use /msg instead.
*
* This setting is ignored when options:servicealias is disabled.
*
* Defaults to the nick of the service if not set.
*/
#alias = "NS"
}
/*
@@ -106,8 +117,7 @@ module
* - memo_mail: Notify user if they have a new memo by mail
* - autoop: User will be automatically opped in channels they enter and have access to
* - neverop: User can not be added to access lists
* - msg: Messages will be sent as PRIVMSGs instead of NOTICEs, requires options:useprivmsg
* to be enabled as well
* - msg: Messages will be sent as PRIVMSGs instead of NOTICEs
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
*
* This directive is optional, if left blank, the options will default to memo_signon, and
@@ -512,7 +522,6 @@ command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpas
* nickserv/set/email, nickserv/saset/email - Used for setting a users email address.
* nickserv/set/keepmodes, nickserv/saset/keepmodes - Configure whether or not services should retain a user's modes across sessions.
* nickserv/set/kill, nickserv/saset/kill - Used for configuring nickname protection.
* nickserv/set/message, nickserv/saset/message - Used to configure how services send messages to you.
* nickserv/set/neverop, nickserv/saset/neverop - Used to configure whether a user can be added to access lists
* nickserv/saset/noexpire - Used for configuring noexpire, which prevents nicks from expiring.
* nickserv/set/password, nickserv/saset/password - Used for changing a users password.
@@ -547,9 +556,6 @@ command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/sa
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; }
command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; permission = "nickserv/saset/password"; }
@@ -569,6 +575,21 @@ module { name = "ns_set_language" }
command { service = "NickServ"; name = "SET LANGUAGE"; command = "nickserv/set/language"; }
command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/saset/language"; permission = "nickserv/saset/language"; }
/*
* ns_set_message
*
* Provides the command nickserv/set/message and nickserv/saset/message.
*
* Allows users to let services send them PRIVMSGs instead of NOTICEs.
*
* This might cause problems with badly written clients as the IRC RFC
* requires that automatic responses to a PRIVMSG use a NOTICE to avoid
* message loops. Only enable this if you are sure this can not happen.
*/
#module { name = "ns_set_message" }
#command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
#command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
/*
* ns_set_misc
*
@@ -582,10 +603,10 @@ command { service = "NickServ"; name = "SET URL"; command = "nickserv/set/misc";
command { service = "NickServ"; name = "SASET URL"; command = "nickserv/saset/misc"; misc_description = _("Associate a URL with this account"); permission = "nickserv/saset/url"; group = "nickserv/admin"; }
#command { service = "NickServ"; name = "SET DISCORD"; command = "nickserv/set/misc"; misc_description = _("Associate a Discord account with your account"); }
#command { service = "NickServ"; name = "SASET DISCORD"; command = "nickserv/saset/misc"; misc_description = _("Associate a Discord account with this account"); permission = "nickserv/saset/discord"; group = "nickserv/admin"; }
#command { service = "NickServ"; name = "SET FACEBOOK"; command = "nickserv/set/misc"; misc_description = _("Associate a Facebook URL with your account"); }
#command { service = "NickServ"; name = "SASET FACEBOOK"; command = "nickserv/saset/misc"; misc_description = _("Associate a Facebook URL with this account"); permission = "nickserv/saset/facebook"; group = "nickserv/admin"; }
#command { service = "NickServ"; name = "SET MASTODON"; command = "nickserv/set/misc"; misc_description = _("Associate a Mastodon account with your account"); }
#command { service = "NickServ"; name = "SASET MASTODON"; command = "nickserv/saset/misc"; misc_description = _("Associate a Mastodon account with this account"); permission = "nickserv/saset/mastodon"; group = "nickserv/admin"; }
#command { service = "NickServ"; name = "SET TIMEZONE"; command = "nickserv/set/misc"; misc_description = _("Associate a time zone with your account"); }
#command { service = "NickServ"; name = "SASET TIMEZONE"; command = "nickserv/saset/misc"; misc_description = _("Associate a time zone with this account"); permission = "nickserv/saset/timezone"; group = "nickserv/admin"; }
/*
* ns_suspend
+11
View File
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
/*
* The server alias that can be used to securely message this service. If
* your IRC server does not have an alias for this service you can set this
* to an empty string to tell users to use /msg instead.
*
* This setting is ignored when options:servicealias is disabled.
*
* Defaults to the nick of the service if not set.
*/
#alias = "OS"
}
/*
+13
View File
@@ -1,3 +1,16 @@
Anope Version 2.1.10
--------------------
Added support for NEXTBANS on UnrealIRCd.
Changed hostmask access entries added by nick to use that nick as the default description.
Changed modes to be handled internally in their split form.
Changed ns_cert to notify a user that their certificate is being automatically added to their account.
Fixed matching users against extended bans.
Fixed parsing name-only extended bans on InspIRCd.
Fixed respecting the preferred extended ban format on InspIRCd.
Fixed the name of the cron script in the docs.
Updated the list of supported IRCds.
Updated the location of the Anope IRC channels
Anope Version 2.1.9
-------------------
Bumped the minimum supported version of UnrealIRCd to 6.
+7
View File
@@ -1,3 +1,10 @@
Anope Version 2.1.10
--------------------
Added options:servicealias.
Moved nickserv/set/message and nickserv/saset/message to the ns_set_message module.
Removed options:useprivmsg.
Removed options:usestrictprivmsg
Anope Version 2.1.9
-------------------
No significant changes.
+1 -1
View File
@@ -90,4 +90,4 @@ Anope DefCon
6) Support
You might get DefCon support by posting on our online forum, or maybe on
our #anope channel at /server irc.anope.org.
our #anope channel at /server irc.teranova.net.
+5 -5
View File
@@ -60,7 +60,7 @@ Note: You should also read the README and FAQ files!
most likely not work!
If you need help, you should visit https://forum.anope.org/ or #anope on
irc.anope.org. Provide *complete* error output, along with other relevant
irc.teranova.net. Provide *complete* error output, along with other relevant
information eg. OS, compiler and C++ library versions.
See the README file for more information.
@@ -111,17 +111,17 @@ Note: You should also read the README and FAQ files!
A crontab entry will allow you to check periodically whether Anope is
still running, and restart it if not.
First rename the example.chk script that is in Anope path (by default,
this is ~/anope/conf) to anope.chk and edit it. You'll need to
First rename the cron.example.sh script that is in Anope path (by default,
this is ~/anope/conf) to cron.sh and edit it. You'll need to
modify the CONFIGURATION part of the file. Then ensure that the file is
marked as executable by typing chmod +x anope.chk, and try to launch the
marked as executable by typing chmod +x cron.sh, and try to launch the
script to see if it works (Anope must not be running when you do this ;))
When this is done, you'll have to add the crontab entry. Type crontab -e.
This will open the default text editor with the crontab file. Enter the
following (with correct path):
*/5 * * * * /home/ircd/anope/conf/anope.chk >/dev/null 2>&1
*/5 * * * * /home/ircd/anope/conf/cron.sh >/dev/null 2>&1
The */5 at the beginning means "check every 5 minutes". You may replace
the 5 with other another number if you want (but less than 60). Consult
+5 -5
View File
@@ -64,7 +64,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
recommandée, et Anope ne fonctionnera probablement pas !
Si vous avez besoin d'aide, vous pouvez aller sur le site
https://forum.anope.org/ ou le canal #anope sur irc.anope.org.
https://forum.anope.org/ ou le canal #anope sur irc.teranova.net.
Fournissez *l'essemble* des erreurs qui apparaîssent, en plus de
toutes informations utiles, comme les versions de votre OS, du
compilateur utilisé et de la librairie C++. Lisez le fichier README
@@ -121,11 +121,11 @@ Note : Vous devrez également lire les fichiers README et FAQ !
Une entrée crontab vous permettra de vérifier périodiquement si Anope
est toujours en cours d'exécution et de le redémarrer s'il n'est pas.
D'abord renommez le script example.chk qui est dans les dossiers
d'Anope (par défaut, ~/anope/conf) en anope.chk et modifiez-le.
D'abord renommez le script cron.example.sh qui est dans les dossiers
d'Anope (par défaut, ~/anope/conf) en cron.sh et modifiez-le.
Vous aurez besoin de modifier la partie CONFIGURATION du fichier.
Assurez-vous ensuite que le fichier est marqué comme exécutable en
tapant chmod +x anope.chk et essayez de lancer le script pour voir
tapant chmod +x cron.sh et essayez de lancer le script pour voir
si cela fonctionne (Anope ne doit pas être en marche lorsque vous
testez cela ;))
@@ -133,7 +133,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
crontab -e. Cela va ouvrir l'éditeur de texte par défaut avec le
fichier crontab. Entrez la ligne suivante (avec le chemin correct) :
*/5 * * * * /home/ircd/anope/conf/anope.chk > /dev/null 2>&1
*/5 * * * * /home/ircd/anope/conf/cron.sh > /dev/null 2>&1
Le */5 au début signifie "vérifier toutes les 5 minutes". Vous pouvez
remplacer le 5 par un autre numéro si vous voulez (mais moins de 60).
+1 -1
View File
@@ -111,7 +111,7 @@ Anope Modules
Use modules at your own risk, and make sure you get them from a
reputable source. You might get module support by contacting the module
author, posting on our online forum, or maybe on our #anope channel
at /server irc.anope.org.
at /server irc.teranova.net.
7) Information for Developers
+3 -3
View File
@@ -167,11 +167,11 @@ Table of Contents
Anope currently works with:
* Bahamut 2.0 or later
* ircd-hybrid 8.2.23 or later
* InspIRCd 3 or later
* ircd-hybrid 8.2.23 or later
* ircd-ratbox 3 or later
* ngIRCd 19.2 or later
* Plexus 3 or later
* Ratbox 2.0.6 or later
* Solanum (all versions)
* UnrealIRCd 6 or later
@@ -245,7 +245,7 @@ Table of Contents
If you read the documentation carefully, and didn't find the answer to
your question, feel free to post on the website forums or join our irc
channel (irc.anope.org #anope). Once you join our Support channel be as
channel (irc.teranova.net #anope). Once you join our Support channel be as
precise as possible when asking a question, because we have no extraordinary
powers and can't guess things if they aren't provided.
+5
View File
@@ -31,6 +31,8 @@ public:
time_t lastmsg;
/* Map of actual command names -> service name/permission required */
CommandInfo::map commands;
/* The server-side alias used to message this bot. */
Anope::string alias;
/* Modes the bot should have as configured in service:modes */
Anope::string botmodes;
/* Channels the bot should be in as configured in service:channels */
@@ -126,6 +128,9 @@ public:
*/
CommandInfo *GetCommand(const Anope::string &cname);
/** Get the command that users can use to send a message to this bot. */
Anope::string GetQueryCommand() const;
/** Find a bot by nick
* @param nick The nick
* @param nick_only True to only look by nick, and not by UID
+1 -1
View File
@@ -215,7 +215,7 @@ public:
* @param mode the modes
* @param enforce_mlock true to enforce mlock
*/
void SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts = 0, bool enforce_mlock = true);
void SetModesInternal(MessageSource &source, const Anope::string &modes, const std::vector<Anope::string> &params, time_t ts = 0, bool enforce_mlock = true);
/** Does the given user match the given list? (CMODE_BAN, CMODE_EXCEPT, etc, a list mode)
* @param u The user
+2 -6
View File
@@ -88,21 +88,17 @@ namespace Configuration
{
/* options:readtimeout */
time_t ReadTimeout;
/* options:useprivmsg */
bool UsePrivmsg;
/* If we should default to privmsging clients */
bool DefPrivmsg;
/* Default language */
Anope::string DefLanguage;
/* options:timeoutcheck */
time_t TimeoutCheck;
/* options:usestrictprivmsg */
bool UseStrictPrivmsg;
/* options:servicealias */
bool ServiceAlias;
/* networkinfo:nickchars */
Anope::string NickChars;
/* either "/msg " or "/" */
Anope::string StrictPrivmsg;
/* List of uplink servers to try and connect to */
std::vector<Uplink> Uplinks;
/* A vector of our logfile options */
+5 -5
View File
@@ -65,9 +65,9 @@ namespace Language
} // namespace Language
/* Commonly used language strings */
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s%s DROP %s %s\002")
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s DROP %s %s\002")
#define SERVICE_UNAVAILABLE _("Sorry, %s is temporarily unavailable.")
#define MORE_INFO _("\002%s%s HELP %s\002 for more information.")
#define MORE_INFO _("\002%s HELP %s\002 for more information.")
#define BAD_USERHOST_MASK _("Mask must be in the form \037user\037@\037host\037.")
#define BAD_EXPIRY_TIME _("Invalid expiry time.")
#define USERHOST_MASK_TOO_WIDE _("%s coverage is too wide; Please use a more specific mask.")
@@ -93,7 +93,7 @@ namespace Language
#define NO_EXPIRE _("does not expire")
#define LIST_INCORRECT_RANGE _("Incorrect range specified. The correct syntax is \002#\037from\037-\037to\037\002.")
#define NICK_IS_SECURE _("This nickname is registered and protected. If it is your\n" \
"nick, type \002%s%s IDENTIFY \037password\037\002. Otherwise,\n" \
"nick, type \002%s IDENTIFY \037password\037\002. Otherwise,\n" \
"please choose a different nick.")
#define FORCENICKCHANGE_NOW _("This nickname has been registered; you may not use it.")
#define NICK_CANNOT_BE_REGISTERED _("Nickname \002%s\002 may not be registered.")
@@ -111,9 +111,9 @@ namespace Language
#define CHAN_INFO_HEADER _("Information about channel \002%s\002:")
#define CHAN_EXCEPTED _("\002%s\002 matches an except on %s and cannot be banned until the except has been removed.")
#define MEMO_NEW_X_MEMO_ARRIVED _("There is a new memo on channel %s.\n" \
"Type \002%s%s READ %s %zu\002 to read it.")
"Type \002%s READ %s %zu\002 to read it.")
#define MEMO_NEW_MEMO_ARRIVED _("You have a new memo from %s.\n" \
"Type \002%s%s READ %zu\002 to read it.")
"Type \002%s READ %zu\002 to read it.")
#define MEMO_HAVE_NO_MEMOS _("You have no memos.")
#define MEMO_X_HAS_NO_MEMOS _("%s has no memos.")
#define MEMO_HAVE_NO_NEW_MEMOS _("You have no new memos.")
+3 -2
View File
@@ -66,10 +66,11 @@ namespace Message
* @param source The source of the SJOIN
* @param chan The channel the users are joining to
* @param ts The TS for the channel
* @param modes The modes sent with the SJOIN, if any
* @param modes The mode letters sent with the SJOIN, if any
* @param modeparams The mode parameters sent with the SJOIN, if any
* @param users The users and their status, if any
*/
static void SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users);
static void SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::vector<Anope::string> &modeparams, const std::list<SJoinUser> &users);
};
struct CoreExport Kick
+4 -1
View File
@@ -216,9 +216,12 @@ template<typename T>
class CoreExport ChannelModeVirtual
: public T
{
Anope::string base;
private:
ChannelMode *basech;
protected:
Anope::string base;
public:
ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename);
+5 -5
View File
@@ -107,14 +107,14 @@ protected:
* @param suid The unique identifier of the user.
* @param nc The account the user is identified as, if any
*/
User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc);
User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const std::vector<Anope::string> &smodeparams, const Anope::string &suid, NickCore *nc);
/** Destroy a user.
*/
virtual ~User();
public:
static User *OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc);
static User *OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc, const std::vector<Anope::string> &smodeparams = {});
/** Update the nickname of a user record accordingly, should be
* called from ircd protocol.
@@ -307,10 +307,10 @@ public:
/** Set a string of modes on a user internally
* @param setter who/what is setting the mode
* @param umodes The modes
* @param umodes The mode letters
* @param umodeparams The mode values
*/
void SetModesInternal(const MessageSource &source, const char *umodes, ...) ATTR_FORMAT(3, 4);
void SetModesInternal(const MessageSource &source, const Anope::string &umodes);
void SetModesInternal(const MessageSource &source, const Anope::string &umodes, const std::vector<Anope::string> &umodeparams = {});
/** Get modes set for this user.
* @return A string of modes set on the user
+80 -72
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-09-26 13:24+0100\n"
"PO-Revision-Date: 2024-09-26 13:25+0100\n"
"POT-Creation-Date: 2024-10-22 16:28+0100\n"
"PO-Revision-Date: 2024-10-22 16:29+0100\n"
"Last-Translator: Sadie Powell <sadie@witchery.services>\n"
"Language-Team: English\n"
"Language: en_US\n"
@@ -82,47 +82,47 @@ msgid ""
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
"below; to use them, type %s%s command. For\n"
"below; to use them, type %s command. For\n"
"more information on a specific command, type\n"
"%s%s %s command.\n"
"%s %s command.\n"
msgstr ""
"%s allows you to have a bot on your own channel.\n"
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
"below; to use them, type %s%s command. For\n"
"below; to use them, type %s command. For\n"
"more information on a specific command, type\n"
"%s%s %s command.\n"
"%s %s command.\n"
#, c-format
msgid ""
"%s allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
"nicknames; to use them, type %s%s command.\n"
"nicknames; to use them, type %s command.\n"
"For more information on a specific command, type\n"
"%s%s %s command.\n"
"%s %s command.\n"
msgstr ""
"%s allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
"nicknames; to use them, type %s%s command.\n"
"nicknames; to use them, type %s command.\n"
"For more information on a specific command, type\n"
"%s%s %s command.\n"
"%s %s command.\n"
#, c-format
msgid ""
"%s allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
"accounts; to use them, type %s%s command.\n"
"accounts; to use them, type %s command.\n"
"For more information on a specific command, type\n"
"%s%s %s command.\n"
"%s %s command.\n"
msgstr ""
"%s allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
"accounts; to use them, type %s%s command.\n"
"accounts; to use them, type %s command.\n"
"For more information on a specific command, type\n"
"%s%s %s command.\n"
"%s %s command.\n"
#, c-format
msgid ""
@@ -131,16 +131,16 @@ msgid ""
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
"%s%s command. For more information on a\n"
"specific command, type %s%s HELP command.\n"
"%s command. For more information on a\n"
"specific command, type %s HELP command.\n"
msgstr ""
"%s allows you to register and control various\n"
"aspects of channels. %s can often prevent\n"
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
"%s%s command. For more information on a\n"
"specific command, type %s%s HELP command.\n"
"%s command. For more information on a\n"
"specific command, type %s HELP command.\n"
#, c-format
msgid "%s already exists in %s bad words list."
@@ -387,8 +387,8 @@ msgid "%s will now permanently be ignored."
msgstr "%s will now permanently be ignored."
#, c-format
msgid "%s%s HELP %s for more information."
msgstr "%s%s HELP %s for more information."
msgid "%s HELP %s for more information."
msgstr "%s HELP %s for more information."
msgid "ADD nick user host real"
msgstr "ADD nick user host real"
@@ -458,11 +458,11 @@ msgstr ""
#, c-format
msgid ""
"User access levels can be seen by using the\n"
"%s command; type %s%s HELP LEVELS for\n"
"%s command; type %s HELP LEVELS for\n"
"information."
msgstr ""
"User access levels can be seen by using the\n"
"%s command; type %s%s HELP LEVELS for\n"
"%s command; type %s HELP LEVELS for\n"
"information."
#, c-format
@@ -947,12 +947,12 @@ msgstr ""
#, c-format
msgid ""
" \n"
"See the %s command (%s%s HELP ACCESS) for\n"
"See the %s command (%s HELP ACCESS) for\n"
"information on giving a subset of these privileges to\n"
"other channel users.\n"
msgstr ""
" \n"
"See the %s command (%s%s HELP ACCESS) for\n"
"See the %s command (%s HELP ACCESS) for\n"
"information on giving a subset of these privileges to\n"
"other channel users.\n"
@@ -1219,11 +1219,11 @@ msgstr ""
#, c-format
msgid ""
" \n"
"Type %s%s HELP command for help on any of the\n"
"Type %s HELP command for help on any of the\n"
"above commands."
msgstr ""
" \n"
"Type %s%s HELP command for help on any of the\n"
"Type %s HELP command for help on any of the\n"
"above commands."
#, c-format
@@ -1249,10 +1249,6 @@ msgstr " Loaded at: %p"
msgid " but %s mysteriously dematerialized."
msgstr " but %s mysteriously dematerialized."
#, c-format
msgid "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
msgstr "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
msgid "\"Jupiter\" a server"
msgstr "\"Jupiter\" a server"
@@ -4790,7 +4786,7 @@ msgid ""
"Maintains the bad words list for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
"type %s%s HELP KICK %s.\n"
"type %s HELP KICK %s.\n"
" \n"
"The ADD command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -4805,7 +4801,7 @@ msgstr ""
"Maintains the bad words list for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
"type %s%s HELP KICK %s.\n"
"type %s HELP KICK %s.\n"
" \n"
"The ADD command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -5414,8 +5410,8 @@ msgid "Persistent"
msgstr "Persistent"
#, c-format
msgid "Please confirm that you want to drop %s with %s%s DROP %s %s"
msgstr "Please confirm that you want to drop %s with %s%s DROP %s %s"
msgid "Please confirm that you want to drop %s with %s DROP %s %s"
msgstr "Please confirm that you want to drop %s with %s DROP %s %s"
msgid "Please contact an Operator to get a vhost assigned to this nick."
msgstr "Please contact an Operator to get a vhost assigned to this nick."
@@ -5911,18 +5907,18 @@ msgstr "Secureops enforced on %s."
#, c-format
msgid ""
"See %s%s HELP %s for more information\n"
"See %s HELP %s for more information\n"
"about the access list."
msgstr ""
"See %s%s HELP %s for more information\n"
"See %s HELP %s for more information\n"
"about the access list."
#, c-format
msgid ""
"See %s%s HELP %s for more information\n"
"See %s HELP %s for more information\n"
"about the flags system."
msgstr ""
"See %s%s HELP %s for more information\n"
"See %s HELP %s for more information\n"
"about the flags system."
msgid "Send a memo to a nick or channel"
@@ -6236,7 +6232,7 @@ msgid ""
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
"BADWORDS command. Type %s%s HELP BADWORDS for\n"
"BADWORDS command. Type %s HELP BADWORDS for\n"
"more information.\n"
" \n"
"ttb is the number of times a user can be kicked\n"
@@ -6247,7 +6243,7 @@ msgstr ""
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
"BADWORDS command. Type %s%s HELP BADWORDS for\n"
"BADWORDS command. Type %s HELP BADWORDS for\n"
"more information.\n"
" \n"
"ttb is the number of times a user can be kicked\n"
@@ -6473,7 +6469,7 @@ msgid ""
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
"Sets various memo options. option can be one of:\n"
@@ -6483,7 +6479,7 @@ msgstr ""
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option."
msgid "Sets various nickname options. option can be one of:"
@@ -6539,8 +6535,8 @@ msgstr ""
"may not get set automatically."
#, c-format
msgid "Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
msgstr "Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
msgid "Setting %s not known. Type %s HELP LEVELS for a list of valid settings."
msgstr "Setting %s not known. Type %s HELP LEVELS for a list of valid settings."
msgid "Setting for DEBUG must be ON, OFF, or a positive number."
msgstr "Setting for DEBUG must be ON, OFF, or a positive number."
@@ -7450,10 +7446,10 @@ msgstr "There is %zu memo on channel %s."
#, c-format
msgid ""
"There is a new memo on channel %s.\n"
"Type %s%s READ %s %zu to read it."
"Type %s READ %s %zu to read it."
msgstr ""
"There is a new memo on channel %s.\n"
"Type %s%s READ %s %zu to read it."
"Type %s READ %s %zu to read it."
#, c-format
msgid "There is no bot assigned to %s anymore."
@@ -7750,20 +7746,20 @@ msgstr "This nickname is suspended."
#, c-format
msgid ""
"This nickname is registered and protected. If it is your\n"
"nick, type %s%s IDENTIFY password. Otherwise,\n"
"nick, type %s IDENTIFY password. Otherwise,\n"
"please choose a different nick."
msgstr ""
"This nickname is registered and protected. If it is your\n"
"nick, type %s%s IDENTIFY password. Otherwise,\n"
"nick, type %s IDENTIFY password. Otherwise,\n"
"please choose a different nick."
#, c-format
msgid "To delete, type: %s%s %s %d"
msgstr "To delete, type: %s%s %s %d"
msgid "To delete, type: %s %s %d"
msgstr "To delete, type: %s %s %d"
#, c-format
msgid "To delete, type: %s%s %s %s %d"
msgstr "To delete, type: %s%s %s %s %d"
msgid "To delete, type: %s %s %s %d"
msgstr "To delete, type: %s %s %s %d"
msgid "To protect ops against bot kicks"
msgstr "To protect ops against bot kicks"
@@ -7918,21 +7914,21 @@ msgstr "Type"
#, c-format
msgid ""
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option."
#, c-format
msgid ""
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
"level SET."
msgstr ""
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
@@ -7940,25 +7936,25 @@ msgstr ""
#, c-format
msgid ""
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option. The options will be set on the given\n"
"nickname."
msgstr ""
"Type %s%s HELP %s option for more information\n"
"Type %s HELP %s option for more information\n"
"on a specific option. The options will be set on the given\n"
"nickname."
#, c-format
msgid ""
"Type %s%s HELP %s option for more information on a\n"
"Type %s HELP %s option for more information on a\n"
"particular option."
msgstr ""
"Type %s%s HELP %s option for more information on a\n"
"Type %s HELP %s option for more information on a\n"
"particular option."
#, c-format
msgid "Type %s%s SET EMAIL email in order to set your email."
msgstr "Type %s%s SET EMAIL email in order to set your email."
msgid "Type %s SET EMAIL email in order to set your email."
msgstr "Type %s SET EMAIL email in order to set your email."
msgid "Un-Load a module"
msgstr "Un-Load a module"
@@ -8006,16 +8002,16 @@ msgid "Unknown command %s."
msgstr "Unknown command %s."
#, c-format
msgid "Unknown command %s. \"%s%s HELP\" for help."
msgstr "Unknown command %s. \"%s%s HELP\" for help."
msgid "Unknown command %s. \"%s HELP\" for help."
msgstr "Unknown command %s. \"%s HELP\" for help."
#, c-format
msgid "Unknown command %s. Did you mean %s?"
msgstr "Unknown command %s. Did you mean %s?"
#, c-format
msgid "Unknown command %s. Did you mean %s? \"%s%s HELP\" for help."
msgstr "Unknown command %s. Did you mean %s? \"%s%s HELP\" for help."
msgid "Unknown command %s. Did you mean %s? \"%s HELP\" for help."
msgstr "Unknown command %s. Did you mean %s? \"%s HELP\" for help."
#, c-format
msgid "Unknown mode character %c ignored."
@@ -8360,10 +8356,6 @@ msgstr "You can't add a channel to its own access list."
msgid "You can't logout %s, they are a Services Operator."
msgstr "You can't logout %s, they are a Services Operator."
#, c-format
msgid "You cannot %s on this network."
msgstr "You cannot %s on this network."
#, c-format
msgid "You cannot set the %c flag."
msgstr "You cannot set the %c flag."
@@ -8438,10 +8430,10 @@ msgstr "You have 1 new memo."
#, c-format
msgid ""
"You have a new memo from %s.\n"
"Type %s%s READ %zu to read it."
"Type %s READ %zu to read it."
msgstr ""
"You have a new memo from %s.\n"
"Type %s%s READ %zu to read it."
"Type %s READ %zu to read it."
#, c-format
msgid "You have been invited to %s by %s."
@@ -8603,6 +8595,10 @@ msgstr "Your IRCd does not support SVSPART."
msgid "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
msgstr "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
#, c-format
msgid "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
msgstr "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
#, c-format
msgid "Your account %s has been successfully created."
msgstr "Your account %s has been successfully created."
@@ -8909,3 +8905,15 @@ msgstr "{nick | channel}"
msgid "{nick | channel} memo-text"
msgstr "{nick | channel} memo-text"
#, c-format
#~ msgid "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
#~ msgstr "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
#, c-format
#~ msgid "To delete, type: %s%s %s %s %d"
#~ msgstr "To delete, type: %s%s %s %s %d"
#, c-format
#~ msgid "You cannot %s on this network."
#~ msgstr "You cannot %s on this network."
+4 -4
View File
@@ -153,11 +153,11 @@ public:
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
"below; to use them, type \002%s%s \037command\037\002. For\n"
"below; to use them, type \002%s \037command\037\002. For\n"
"more information on a specific command, type\n"
"\002%s%s %s \037command\037\002.\n"),
BotServ->nick.c_str(), Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(),
Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(), source.command.c_str());
"\002%s %s \037command\037\002.\n"),
BotServ->nick.c_str(), BotServ->GetQueryCommand().c_str(),
BotServ->GetQueryCommand().c_str(), source.command.c_str());
}
return EVENT_CONTINUE;
+2 -2
View File
@@ -430,7 +430,7 @@ public:
source.Reply(_("Maintains the \002bad words list\002 for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
"type \002%s%s HELP KICK %s\002.\n"
"type \002%s HELP KICK %s\002.\n"
" \n"
"The \002ADD\002 command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -440,7 +440,7 @@ public:
"will be done if a user says a word that ends with\n"
"\037word\037. If you don't specify anything, a kick will\n"
"be issued every time \037word\037 is said by a user.\n"
" \n"), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
" \n"), source.service->GetQueryCommand().c_str(), source.command.c_str());
source.Reply(_("The \002DEL\002 command removes the given word from the\n"
"bad words list. If a list of entry numbers is given, those\n"
"entries are deleted. (See the example for LIST below.)\n"
+4 -4
View File
@@ -153,11 +153,11 @@ public:
}
}
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
"level SET."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
"level SET."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
@@ -308,12 +308,12 @@ public:
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
"\002BADWORDS\002 command. Type \002%s%s HELP BADWORDS\002 for\n"
"\002BADWORDS\002 command. Type \002%s HELP BADWORDS\002 for\n"
"more information.\n"
" \n"
"\037ttb\037 is the number of times a user can be kicked\n"
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
"the ban system once activated."), source.service->GetQueryCommand().c_str());
return true;
}
};
+2 -2
View File
@@ -58,8 +58,8 @@ public:
}
}
}
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n"
"particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information on a\n"
"particular option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
+7 -4
View File
@@ -262,9 +262,9 @@ public:
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
"\002%s%s \037command\037\002. For more information on a\n"
"specific command, type \002%s%s HELP \037command\037\002.\n"),
ChanServ->nick.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str());
"\002%s \037command\037\002. For more information on a\n"
"specific command, type \002%s HELP \037command\037\002.\n"),
ChanServ->nick.c_str(), ChanServ->nick.c_str(), ChanServ->GetQueryCommand().c_str(), ChanServ->GetQueryCommand().c_str());
return EVENT_CONTINUE;
}
@@ -382,8 +382,11 @@ public:
return EVENT_CONTINUE;
}
void OnPostInit() override
void OnUplinkSync(Server* s) override
{
// We need to do this when the uplink is synced as we may not know if
// the mode exists before then on some IRCds (e.g. InspIRCd).
if (!persist)
return;
+14 -5
View File
@@ -87,6 +87,7 @@ class CommandCSAccess final
void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{
Anope::string mask = params[2];
Anope::string description = params.size() > 4 ? params[4] : "";
Privilege *p = NULL;
int level = ACCESS_INVALID;
@@ -172,7 +173,11 @@ class CommandCSAccess final
{
User *targ = User::Find(mask, true);
if (targ != NULL)
{
mask = "*!*@" + targ->GetDisplayedHost();
if (description.empty())
description = targ->nick;
}
else
{
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
@@ -216,7 +221,7 @@ class CommandCSAccess final
access->level = level;
access->last_seen = 0;
access->created = Anope::CurTime;
access->description = params.size() > 4 ? params[4] : "";
access->description = description;
ci->AddAccess(access);
FOREACH_MOD(OnAccessAdd, (ci, source, access));
@@ -625,8 +630,8 @@ public:
Anope::string cmd;
if (Command::FindCommandFromService("chanserv/levels", bi, cmd))
source.Reply(_("\002User access levels\002 can be seen by using the\n"
"\002%s\002 command; type \002%s%s HELP LEVELS\002 for\n"
"information."), cmd.c_str(), Config->StrictPrivmsg.c_str(), bi->nick.c_str());
"\002%s\002 command; type \002%s HELP LEVELS\002 for\n"
"information."), cmd.c_str(), bi->GetQueryCommand().c_str());
return true;
}
};
@@ -660,7 +665,10 @@ class CommandCSLevels final
{
Privilege *p = PrivilegeManager::FindPrivilege(what);
if (p == NULL)
source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
{
source.Reply(_("Setting \002%s\002 not known. Type \002%s HELP LEVELS\002 for a list of valid settings."),
what.c_str(), source.service->GetQueryCommand().c_str());
}
else
{
bool override = !source.AccessFor(ci).HasPriv("FOUNDER");
@@ -701,7 +709,8 @@ class CommandCSLevels final
return;
}
source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
source.Reply(_("Setting \002%s\002 not known. Type \002%s HELP LEVELS\002 for a list of valid settings."),
what.c_str(), source.service->GetQueryCommand().c_str());
}
static void DoList(CommandSource &source, ChannelInfo *ci)
+2 -2
View File
@@ -58,8 +58,8 @@ public:
*code = Anope::Random(15);
}
source.Reply(CONFIRM_DROP, ci->name.c_str(), Config->StrictPrivmsg.c_str(),
source.service->nick.c_str(), ci->name.c_str(), code->c_str());
source.Reply(CONFIRM_DROP, ci->name.c_str(), source.service->GetQueryCommand().c_str(),
ci->name.c_str(), code->c_str());
return;
}
+5 -1
View File
@@ -79,7 +79,7 @@ FlagsAccessProvider *FlagsAccessProvider::ap;
class CommandCSFlags final
: public Command
{
void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags, const Anope::string &description)
void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags, Anope::string description)
{
if (flags.empty())
{
@@ -131,7 +131,11 @@ class CommandCSFlags final
{
User *targ = User::Find(mask, true);
if (targ != NULL)
{
mask = "*!*@" + targ->GetDisplayedHost();
if (description.empty())
description = targ->nick;
}
else
{
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
+2 -2
View File
@@ -100,9 +100,9 @@ public:
Anope::string cmd;
if (Command::FindCommandFromService("chanserv/access", bi, cmd))
source.Reply(_(" \n"
"See the \002%s\002 command (\002%s%s HELP ACCESS\002) for\n"
"See the \002%s\002 command (\002%s HELP ACCESS\002) for\n"
"information on giving a subset of these privileges to\n"
"other channel users.\n"), cmd.c_str(), Config->StrictPrivmsg.c_str(), bi->nick.c_str());
"other channel users.\n"), cmd.c_str(), bi->GetQueryCommand().c_str());
source.Reply(_(" \n"
"NOTICE: In order to register a channel, you must have\n"
"first registered your nickname."));
+8 -6
View File
@@ -59,8 +59,8 @@ public:
c->OnServHelp(source);
}
}
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n"
"particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information on a\n"
"particular option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
};
@@ -513,12 +513,13 @@ public:
/* Set the perm mode */
if (cm)
{
if (ci->c && !ci->c->HasMode("PERM"))
ci->c->SetMode(NULL, cm);
/* Add it to the channels mlock */
ModeLocks *ml = ci->Require<ModeLocks>("modelocks");
if (ml)
ml->SetMLock(cm, true, "", source.GetNick());
if (ci->c && !ci->c->HasMode("PERM"))
ci->c->SetMode(NULL, cm);
}
/* No botserv bot, no channel mode, give them ChanServ.
* Yes, this works fine with no BotServ.
@@ -556,12 +557,13 @@ public:
/* Unset perm mode */
if (cm)
{
if (ci->c && ci->c->HasMode("PERM"))
ci->c->RemoveMode(NULL, cm);
/* Remove from mlock */
ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks");
if (ml)
ml->RemoveMLock(cm, true);
if (ci->c && ci->c->HasMode("PERM"))
ci->c->RemoveMode(NULL, cm);
}
/* No channel mode, no BotServ, but using ChanServ as the botserv bot
* which was assigned when persist was set on
+31 -41
View File
@@ -11,57 +11,47 @@
class StatusUpdate final
: public Module
{
public:
StatusUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
private:
void OnAccessChange(ChannelInfo *ci, ChanAccess *access, bool adding)
{
if (!ci->c)
return;
for (const auto &[_, uc] : ci->c->users)
{
auto *user = uc->user;
ChannelInfo *next;
if (user->server != Me && access->Matches(user, user->Account(), next))
{
auto ag = ci->AccessFor(user);
for (auto *cms : ModeManager::GetStatusChannelModesByRank())
{
if (!ag.HasPriv("AUTO" + cms->name))
ci->c->RemoveMode(NULL, cms, user->GetUID());
}
if (adding)
ci->c->SetCorrectModes(user, true);
}
}
}
public:
StatusUpdate(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, VENDOR)
{
}
void OnAccessAdd(ChannelInfo *ci, CommandSource &, ChanAccess *access) override
{
if (ci->c)
{
for (const auto &[_, uc] : ci->c->users)
{
User *user = uc->user;
ChannelInfo *next;
if (user->server != Me && access->Matches(user, user->Account(), next))
{
AccessGroup ag = ci->AccessFor(user);
for (auto *cms : ModeManager::GetStatusChannelModesByRank())
{
if (!ag.HasPriv("AUTO" + cms->name))
ci->c->RemoveMode(NULL, cms, user->GetUID());
}
ci->c->SetCorrectModes(user, true);
}
}
}
OnAccessChange(ci, access, true);
}
void OnAccessDel(ChannelInfo *ci, CommandSource &, ChanAccess *access) override
{
if (ci->c)
{
for (const auto &[_, uc] : ci->c->users)
{
User *user = uc->user;
ChannelInfo *next;
if (user->server != Me && access->Matches(user, user->Account(), next))
{
AccessGroup ag = ci->AccessFor(user);
for (auto *cms : ModeManager::GetStatusChannelModesByRank())
{
if (!ag.HasPriv("AUTO" + cms->name))
ci->c->RemoveMode(NULL, cms, user->GetUID());
}
}
}
}
OnAccessChange(ci, access, false);
}
};
+8 -4
View File
@@ -179,7 +179,11 @@ private:
{
User *targ = User::Find(mask, true);
if (targ != NULL)
{
mask = "*!*@" + targ->GetDisplayedHost();
if (description.empty())
description = targ->nick;
}
else
{
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
@@ -590,11 +594,11 @@ public:
source.Reply(_("Alternative methods of modifying channel access lists are\n"
"available."));
if (!access_cmd.empty())
source.Reply(_("See \002%s%s HELP %s\002 for more information\n"
"about the access list."), Config->StrictPrivmsg.c_str(), access_bi->nick.c_str(), access_cmd.c_str());
source.Reply(_("See \002%s HELP %s\002 for more information\n"
"about the access list."), access_bi->GetQueryCommand().c_str(), access_cmd.c_str());
if (!flags_cmd.empty())
source.Reply(_("See \002%s%s HELP %s\002 for more information\n"
"about the flags system."), Config->StrictPrivmsg.c_str(), flags_bi->nick.c_str(), flags_cmd.c_str());
source.Reply(_("See \002%s HELP %s\002 for more information\n"
"about the flags system."), flags_bi->GetQueryCommand().c_str(), flags_cmd.c_str());
}
return true;
}
+4 -4
View File
@@ -101,7 +101,7 @@ public:
if (ci->AccessFor(cu->user).HasPriv("MEMO"))
{
if (cu->user->Account() && cu->user->Account()->HasExt("MEMO_RECEIVE"))
cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), ci->name.c_str(), mi->memos->size());
cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), MemoServ->GetQueryCommand().c_str(), ci->name.c_str(), mi->memos->size());
}
}
}
@@ -116,7 +116,7 @@ public:
{
User *user = User::Find(na->nick, true);
if (user && user->IsIdentified())
user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), mi->memos->size());
user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), MemoServ->GetQueryCommand().c_str(), mi->memos->size());
}
}
@@ -229,8 +229,8 @@ public:
if (!params.empty() || source.c || source.service != *MemoServ)
return;
source.Reply(_(" \n"
"Type \002%s%s HELP \037command\037\002 for help on any of the\n"
"above commands."), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str());
"Type \002%s HELP \037command\037\002 for help on any of the\n"
"above commands."), MemoServ->GetQueryCommand().c_str());
}
};
+2 -2
View File
@@ -91,9 +91,9 @@ public:
if (Command::FindCommandFromService("memoserv/del", bi, cmd))
{
if (ci)
source.Reply(_("To delete, type: \002%s%s %s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), ci->name.c_str(), index + 1);
source.Reply(_("To delete, type: \002%s %s %s %d\002"), bi->GetQueryCommand().c_str(), cmd.c_str(), ci->name.c_str(), index + 1);
else
source.Reply(_("To delete, type: \002%s%s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), index + 1);
source.Reply(_("To delete, type: \002%s %s %d\002"), bi->GetQueryCommand().c_str(), cmd.c_str(), index + 1);
}
source.Reply("%s", m->text.c_str());
+2 -2
View File
@@ -232,8 +232,8 @@ public:
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
"Type \002%s%s HELP %s \037option\037\002 for more information\n"
"on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
"Type \002%s HELP %s \037option\037\002 for more information\n"
"on a specific option."), source.service->GetQueryCommand().c_str(), source.command.c_str());
}
else if (subcommand.equals_ci("NOTIFY"))
source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n"
+8 -8
View File
@@ -98,7 +98,7 @@ class NickServRelease final
public:
NickServRelease(Module *me, NickAlias *na, time_t delay)
: User(na->nick, Config->GetModule("nickserv")->Get<const Anope::string>("enforceruser", "user"), Config->GetModule("nickserv")->Get<const Anope::string>("enforcerhost", Me->GetName()), "", "", Me, "Services Enforcer", Anope::CurTime, "", IRCD->UID_Retrieve(), NULL)
: User(na->nick, Config->GetModule("nickserv")->Get<const Anope::string>("enforceruser", "user"), Config->GetModule("nickserv")->Get<const Anope::string>("enforcerhost", Me->GetName()), "", "", Me, "Services Enforcer", Anope::CurTime, "", {}, IRCD->UID_Retrieve(), NULL)
, Timer(me, delay)
, nick(na->nick)
{
@@ -195,7 +195,7 @@ public:
if (!na->nc->HasExt("KILL_IMMED"))
{
u->SendMessage(NickServ, NICK_IS_SECURE, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
u->SendMessage(NickServ, NICK_IS_SECURE, NickServ->GetQueryCommand().c_str());
}
if (na->nc->HasExt("KILLPROTECT"))
{
@@ -362,8 +362,8 @@ public:
u->SendMessage(NickServ, _("You must now supply an email for your nick.\n"
"This email will allow you to retrieve your password in\n"
"case you forget it."));
u->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037email\037\002 in order to set your email."),
Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
u->SendMessage(NickServ, _("Type \002%s SET EMAIL \037email\037\002 in order to set your email."),
NickServ->GetQueryCommand().c_str());
}
for (auto *c : collides)
@@ -465,15 +465,15 @@ public:
source.Reply(_("\002%s\002 allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
"nicknames; to use them, type \002%s%s \037command\037\002.\n"
"nicknames; to use them, type \002%s \037command\037\002.\n"
"For more information on a specific command, type\n"
"\002%s%s %s \037command\037\002.\n"), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), source.command.c_str());
"\002%s %s \037command\037\002.\n"), NickServ->nick.c_str(), NickServ->GetQueryCommand().c_str(), NickServ->GetQueryCommand().c_str(), source.command.c_str());
else
source.Reply(_("\002%s\002 allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
"accounts; to use them, type \002%s%s \037command\037\002.\n"
"accounts; to use them, type \002%s \037command\037\002.\n"
"For more information on a specific command, type\n"
"\002%s%s %s \037command\037\002.\n"), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), source.command.c_str());
"\002%s %s \037command\037\002.\n"), NickServ->nick.c_str(), NickServ->GetQueryCommand().c_str(), NickServ->GetQueryCommand().c_str(), source.command.c_str());
return EVENT_CONTINUE;
}
+3
View File
@@ -425,6 +425,9 @@ public:
auto *cl = certs.Require(na->nc);
cl->AddCert(u->fingerprint);
auto *NickServ = Config->GetClient("NickServ");
u->SendMessage(NickServ, _("Your SSL certificate fingerprint \002%s\002 has been automatically added to your certificate list."), u->fingerprint.c_str());
}
EventReturn OnNickValidate(User *u, NickAlias *na) override
+2 -2
View File
@@ -72,8 +72,8 @@ public:
*code = Anope::Random(15);
}
source.Reply(CONFIRM_DROP, na->nick.c_str(), Config->StrictPrivmsg.c_str(),
source.service->nick.c_str(), na->nick.c_str(), code->c_str());
source.Reply(CONFIRM_DROP, na->nick.c_str(), source.service->GetQueryCommand().c_str(),
na->nick.c_str(), code->c_str());
return;
}
+6 -118
View File
@@ -57,8 +57,8 @@ public:
}
}
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
"on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
"on a specific option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
@@ -100,9 +100,9 @@ public:
}
}
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
"on a specific option. The options will be set on the given\n"
"\037nickname\037."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
"\037nickname\037."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
};
@@ -892,112 +892,6 @@ public:
}
};
class CommandNSSetMessage
: public Command
{
public:
CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1) : Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Change the communication method of services"));
this->SetSyntax("{ON | OFF}");
}
void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
{
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
return;
}
const NickAlias *na = NickAlias::Find(user);
if (!na)
{
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
return;
}
NickCore *nc = na->nc;
if (!Config->GetBlock("options")->Get<bool>("useprivmsg"))
{
source.Reply(_("You cannot %s on this network."), source.command.c_str());
return;
}
EventReturn MOD_RESULT;
FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
if (MOD_RESULT == EVENT_STOP)
return;
if (param.equals_ci("ON"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display;
nc->Extend<bool>("MSG");
source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str());
}
else if (param.equals_ci("OFF"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display;
nc->Shrink<bool>("MSG");
source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str());
}
else
this->OnSyntaxError(source, "MSG");
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, source.nc->display, params[0]);
}
bool OnHelp(CommandSource &source, const Anope::string &) override
{
Anope::string cmd = source.command;
size_t i = cmd.find_last_of(' ');
if (i != Anope::string::npos)
cmd = cmd.substr(i + 1);
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows you to choose the way services are communicating with\n"
"you. With \002%s\002 set, services will use messages, else they'll\n"
"use notices."), cmd.upper().c_str());
return true;
}
void OnServHelp(CommandSource &source) override
{
if (Config->GetBlock("options")->Get<bool>("useprivmsg"))
Command::OnServHelp(source);
}
};
class CommandNSSASetMessage final
: public CommandNSSetMessage
{
public:
CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2)
{
this->ClearSyntax();
this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
}
bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows you to choose the way services are communicating with\n"
"the given user. With \002MSG\002 set, services will use messages,\n"
"else they'll use notices."));
return true;
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, params[0], params[1]);
}
};
class CommandNSSASetNoexpire final
: public Command
{
@@ -1075,16 +969,13 @@ class NSSet final
CommandNSSetKill commandnssetkill;
CommandNSSASetKill commandnssasetkill;
CommandNSSetMessage commandnssetmessage;
CommandNSSASetMessage commandnssasetmessage;
CommandNSSetPassword commandnssetpassword;
CommandNSSASetPassword commandnssasetpassword;
CommandNSSASetNoexpire commandnssasetnoexpire;
SerializableExtensibleItem<bool> autoop, neverop, killprotect, kill_quick, kill_immed,
message, noexpire;
noexpire;
struct KeepModes final
: SerializableExtensibleItem<bool>
@@ -1145,13 +1036,12 @@ public:
commandnssetemail(this), commandnssasetemail(this),
commandnssetkeepmodes(this), commandnssasetkeepmodes(this),
commandnssetkill(this), commandnssasetkill(this),
commandnssetmessage(this), commandnssasetmessage(this),
commandnssetpassword(this), commandnssasetpassword(this),
commandnssasetnoexpire(this),
autoop(this, "AUTOOP"), neverop(this, "NEVEROP"),
killprotect(this, "KILLPROTECT"), kill_quick(this, "KILL_QUICK"),
kill_immed(this, "KILL_IMMED"), message(this, "MSG"),
kill_immed(this, "KILL_IMMED"),
noexpire(this, "NS_NO_EXPIRE"),
keep_modes(this, "NS_KEEP_MODES"), ns_set_email(this, "ns_set_email")
@@ -1208,8 +1098,6 @@ public:
info.AddOption(_("Quick protection"));
else if (killprotect.HasExt(na->nc))
info.AddOption(_("Protection"));
if (message.HasExt(na->nc))
info.AddOption(_("Message mode"));
if (autoop.HasExt(na->nc))
info.AddOption(_("Auto-op"));
if (neverop.HasExt(na->nc))
+137
View File
@@ -0,0 +1,137 @@
/* NickServ core functions
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*/
#include "module.h"
class CommandNSSetMessage
: public Command
{
public:
CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1)
: Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Change the communication method of services"));
this->SetSyntax("{ON | OFF}");
}
void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
{
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
return;
}
const NickAlias *na = NickAlias::Find(user);
if (!na)
{
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
return;
}
NickCore *nc = na->nc;
EventReturn MOD_RESULT;
FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
if (MOD_RESULT == EVENT_STOP)
return;
if (param.equals_ci("ON"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display;
nc->Extend<bool>("MSG");
source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str());
}
else if (param.equals_ci("OFF"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display;
nc->Shrink<bool>("MSG");
source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str());
}
else
this->OnSyntaxError(source, "MSG");
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, source.nc->display, params[0]);
}
bool OnHelp(CommandSource &source, const Anope::string &) override
{
Anope::string cmd = source.command;
size_t i = cmd.find_last_of(' ');
if (i != Anope::string::npos)
cmd = cmd.substr(i + 1);
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows you to choose the way services are communicating with\n"
"you. With \002%s\002 set, services will use messages, else they'll\n"
"use notices."), cmd.upper().c_str());
return true;
}
};
class CommandNSSASetMessage final
: public CommandNSSetMessage
{
public:
CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2)
{
this->ClearSyntax();
this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
}
bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows you to choose the way services are communicating with\n"
"the given user. With \002MSG\002 set, services will use messages,\n"
"else they'll use notices."));
return true;
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, params[0], params[1]);
}
};
class NSSetMessage final
: public Module
{
private:
CommandNSSetMessage commandnssetmessage;
CommandNSSASetMessage commandnssasetmessage;
SerializableExtensibleItem<bool> message;
public:
NSSetMessage(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, VENDOR)
, commandnssetmessage(this)
, commandnssasetmessage(this)
, message(this, "MSG")
{
}
void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
{
if (!show_hidden)
return;
if (message.HasExt(na->nc))
info.AddOption(_("Message mode"));
}
};
MODULE_INIT(NSSetMessage)
+7 -10
View File
@@ -312,12 +312,8 @@ struct IRCDMessageMode final
Channel *c = Channel::Find(params[0]);
auto ts = IRCD->ExtractTimestamp(params[1]);
Anope::string modes = params[2];
for (unsigned int i = 3; i < params.size(); ++i)
modes += " " + params[i];
if (c)
c->SetModesInternal(source, modes, ts);
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
}
else
{
@@ -400,11 +396,12 @@ struct IRCDMessageSJoin final
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string modes;
std::vector<Anope::string> modeparams;
if (params.size() >= 4)
for (unsigned i = 2; i < params.size(); ++i)
modes += " " + params[i];
if (!modes.empty())
modes.erase(modes.begin());
{
modes = params[2];
modeparams = { params.begin() + 3, params.end() };
}
std::list<Message::Join::SJoinUser> users;
@@ -445,7 +442,7 @@ struct IRCDMessageSJoin final
}
auto ts = IRCD->ExtractTimestamp(params[0]);
Message::Join::SJoin(source, params[1], ts, modes, users);
Message::Join::SJoin(source, params[1], ts, modes, modeparams, users);
}
};
+2 -14
View File
@@ -547,14 +547,6 @@ struct IRCDMessageSJoin final
/* :0MC SJOIN 1654877335 #nether +nt :@0MCAAAAAB +0MCAAAAAC */
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string modes;
for (unsigned i = 2; i < params.size() - 1; ++i)
modes += " " + params[i];
if (!modes.empty())
modes.erase(modes.begin());
std::list<Message::Join::SJoinUser> users;
spacesepstream sep(params[params.size() - 1]);
@@ -582,7 +574,7 @@ struct IRCDMessageSJoin final
}
auto ts = IRCD->ExtractTimestamp(params[0]);
Message::Join::SJoin(source, params[1], ts, modes, users);
Message::Join::SJoin(source, params[1], ts, params[2], { params.begin() + 3, params.end() - 1 }, users);
}
};
@@ -637,13 +629,9 @@ struct IRCDMessageTMode final
{
auto ts = IRCD->ExtractTimestamp(params[0]);
Channel *c = Channel::Find(params[1]);
Anope::string modes = params[2];
for (unsigned i = 3; i < params.size(); ++i)
modes += " " + params[i];
if (c)
c->SetModesInternal(source, modes, ts);
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
}
};
+33 -62
View File
@@ -27,6 +27,9 @@ struct SASLUser final
namespace
{
/** Whether we should send extbans using their named form. */
bool named_extbans = false;
// The SID of a server we are waiting to squit.
Anope::string rsquit_id;
@@ -723,7 +726,8 @@ namespace InspIRCdExtBan
ChannelMode *Wrap(Anope::string &param) override
{
param = Anope::string(xbchar) + ":" + param;
auto xbprefix = named_extbans || !xbchar ? xbname : Anope::string(xbchar);
param = xbprefix + ":" + param;
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
}
@@ -757,10 +761,7 @@ namespace InspIRCdExtBan
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
return Entry(this->name, real_mask).Matches(u);
return Entry(this->name, e->GetMask()).Matches(u);
}
};
@@ -775,10 +776,7 @@ namespace InspIRCdExtBan
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string channel = mask.substr(2);
auto channel = e->GetMask();
ChannelMode *cm = NULL;
if (channel[0] != '#')
{
@@ -813,10 +811,7 @@ namespace InspIRCdExtBan
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
return u->IsIdentified() && real_mask.equals_ci(u->Account()->display);
return u->IsIdentified() && e->GetMask().equals_ci(u->Account()->display);
}
};
@@ -831,9 +826,7 @@ namespace InspIRCdExtBan
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
return Anope::Match(u->realname, real_mask);
return Anope::Match(u->realname, e->GetMask());
}
};
@@ -848,9 +841,7 @@ namespace InspIRCdExtBan
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
return Anope::Match(u->server->GetName(), real_mask);
return Anope::Match(u->server->GetName(), e->GetMask());
}
};
@@ -865,9 +856,7 @@ namespace InspIRCdExtBan
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, e->GetMask());
}
};
@@ -882,9 +871,7 @@ namespace InspIRCdExtBan
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
return !u->Account() && Entry("BAN", real_mask).Matches(u);
return !u->Account() && Entry(this->base, e->GetMask()).Matches(u);
}
};
@@ -903,9 +890,7 @@ namespace InspIRCdExtBan
if (!opertype)
return false; // Not an operator.
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
return Anope::Match(opertype->replace_all_cs(' ', '_'), real_mask);
return Anope::Match(opertype->replace_all_cs(' ', '_'), e->GetMask());
}
};
}
@@ -1091,19 +1076,25 @@ struct IRCDMessageCapab final
static bool ParseExtBan(const Anope::string &token, ExtBanInfo &extban)
{
// acting:foo=f matching:foo=f
// A B A B
// acting:foo=f matching:bar=b matching:baz
// A B A B A
auto a = token.find(':');
if (a == Anope::string::npos)
return false;
auto b = token.find(':', a + 1);
auto b = token.find('=', a + 1);
if (b == Anope::string::npos)
return false;
{
// ExtBan only has a name.
extban.name = token.substr(a + 1);
}
else
{
// ExtBan has a name and letter.
extban.name = token.substr(a + 1, b - a - 1);
extban.letter = token[b + 1];
}
extban.type = token.substr(0, a);
extban.name = token.substr(a + 1, b - a - 1);
extban.letter = token[b + 1];
if (Anope::ProtocolDebug)
Log(LOG_DEBUG) << "Parsed extban: type=" << extban.type << " name=" << extban.name << " letter=" << extban.letter;
@@ -1573,6 +1564,8 @@ struct IRCDMessageCapab final
auto [tokname, tokvalue] = ParseCapability(capab);
if (tokname == "CHALLENGE")
challenge = tokvalue;
if (tokname == "EXTBANFORMAT")
named_extbans = tokvalue.equals_ci("any") || tokvalue.equals_ci("name");
else if (tokname == "MAXCHANNEL")
IRCD->MaxChannel = Anope::Convert<size_t>(tokvalue, IRCD->MaxChannel);
else if (tokname == "MAXHOST")
@@ -2056,15 +2049,6 @@ struct IRCDMessageFJoin final
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string modes;
if (params.size() >= 3)
{
for (unsigned i = 2; i < params.size() - 1; ++i)
modes += " " + params[i];
if (!modes.empty())
modes.erase(modes.begin());
}
std::list<Message::Join::SJoinUser> users;
spacesepstream sep(params[params.size() - 1]);
@@ -2102,7 +2086,7 @@ struct IRCDMessageFJoin final
}
auto ts = IRCD->ExtractTimestamp(params[1]);
Message::Join::SJoin(source, params[0], ts, modes, users);
Message::Join::SJoin(source, params[0], ts, params[2], { params.begin() + 3, params.end() - 1 }, users);
}
};
@@ -2114,15 +2098,10 @@ struct IRCDMessageFMode final
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
/* :source FMODE #test 12345678 +nto foo */
Anope::string modes = params[2];
for (unsigned n = 3; n < params.size(); ++n)
modes += " " + params[n];
Channel *c = Channel::Find(params[0]);
auto ts = IRCD->ExtractTimestamp(params[1]);
if (c)
c->SetModesInternal(source, modes, ts);
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
}
};
@@ -2198,7 +2177,7 @@ struct IRCDMessageIJoin final
std::list<Message::Join::SJoinUser> users;
users.push_back(user);
Message::Join::SJoin(source, params[0], chants, "", users);
Message::Join::SJoin(source, params[0], chants, "", {}, users);
}
};
@@ -2250,12 +2229,8 @@ struct IRCDMessageMode final
{
Channel *c = Channel::Find(params[0]);
Anope::string modes = params[1];
for (unsigned n = 2; n < params.size(); ++n)
modes += " " + params[n];
if (c)
c->SetModesInternal(source, modes);
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() });
}
else
{
@@ -2415,10 +2390,6 @@ struct IRCDMessageUID final
size_t offset = params[8][0] == '+' ? 0 : 1;
auto ts = IRCD->ExtractTimestamp(params[1]);
Anope::string modes = params[8+offset];
for (unsigned i = 9+offset; i < params.size() - 1; ++i)
modes += " " + params[i];
NickAlias *na = NULL;
if (SASL::sasl)
for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
@@ -2436,7 +2407,7 @@ struct IRCDMessageUID final
++it;
}
User *u = User::OnIntroduce(params[2], params[5+offset], params[3], params[4], params[6+offset], source.GetServer(), params[params.size() - 1], ts, modes, params[0], na ? *na->nc : NULL);
auto *u = User::OnIntroduce(params[2], params[5+offset], params[3], params[4], params[6+offset], source.GetServer(), params[params.size() - 1], ts, params[8 + offset], params[0], na ? *na->nc : NULL, { params.begin() + 9 + offset, params.end() - 1 });
if (u)
u->signon = IRCD->ExtractTimestamp(params[7+offset]);
}
+10 -13
View File
@@ -224,7 +224,7 @@ struct IRCDMessageChaninfo final
bool created;
Channel *c = Channel::FindOrCreate(params[0], created);
Anope::string modes = params[1];
std::vector<Anope::string> modeparams;
if (params.size() == 3)
{
@@ -237,17 +237,17 @@ struct IRCDMessageChaninfo final
switch(params[1][i])
{
case 'k':
modes += " " + params[2];
modeparams.push_back(params[2]);
continue;
case 'l':
modes += " " + params[3];
modeparams.push_back(params[3]);
continue;
}
}
c->ChangeTopicInternal(NULL, source.GetName(), params[4], Anope::CurTime);
}
c->SetModesInternal(source, modes);
c->SetModesInternal(source, params[1], modeparams);
}
};
@@ -267,11 +267,13 @@ struct IRCDMessageJoin final
User *user = source.GetUser();
size_t pos = params[0].find('\7');
Anope::string channel, modes;
std::vector<Anope::string> modeparams;
if (pos != Anope::string::npos)
{
channel = params[0].substr(0, pos);
modes = '+' + params[0].substr(pos+1, params[0].length()) + " " + user->nick;
modes = '+' + params[0].substr(pos+1, params[0].length());
modeparams.push_back(user->nick);
}
else
{
@@ -287,7 +289,7 @@ struct IRCDMessageJoin final
{
Channel *c = Channel::Find(channel);
if (c)
c->SetModesInternal(source, modes);
c->SetModesInternal(source, modes, modeparams);
}
}
};
@@ -367,17 +369,12 @@ struct IRCDMessageMode final
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string modes = params[1];
for (size_t i = 2; i < params.size(); ++i)
modes += " " + params[i];
if (IRCD->IsChannelValid(params[0]))
{
Channel *c = Channel::Find(params[0]);
if (c)
c->SetModesInternal(source, modes);
c->SetModesInternal(source, params[1], { params.begin() + 2, params.end() });
}
else
{
@@ -485,7 +482,7 @@ struct IRCDMessageNJoin final
users.push_back(sju);
}
Message::Join::SJoin(source, params[0], 0, "", users);
Message::Join::SJoin(source, params[0], 0, "", {}, users);
}
};
+1 -1
View File
@@ -33,7 +33,7 @@ class RatboxProto final
}
public:
RatboxProto(Module *creator) : IRCDProto(creator, "Ratbox 3.0+")
RatboxProto(Module *creator) : IRCDProto(creator, "ircd-ratbox 3+")
{
DefaultPseudoclientModes = "+oiS";
CanSNLine = true;
+111 -105
View File
@@ -14,7 +14,25 @@
#include "modules/sasl.h"
typedef Anope::map<Anope::string> ModData;
static Anope::string UplinkSID;
namespace
{
Anope::string UplinkSID;
bool IsExtBan(const Anope::string &str, Anope::string &name, Anope::string &value)
{
if (str[0] != '~')
return false;
auto endpos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1);
if (endpos == Anope::string::npos || str[endpos] != ':' || endpos+1 == str.length())
return false;
name = str.substr(1, endpos - 1);
value = str.substr(endpos + 1);
return true;
}
}
class UnrealIRCdProto final
: public IRCDProto
@@ -225,9 +243,10 @@ private:
// EAUTH: communicates information about the local server.
// MLOCK: enable receiving the MLOCK message when a mode lock changes.
// MTAGS: enable receiving IRCv3 message tags.
// NEXTBANS: enables receiving named extended bans.
// SID: communicates the unique identifier of the local server.
// VHP: enable receiving the vhost in UID.
Uplink::Send("PROTOCTL", "BIGLINES", "MLOCK", "MTAGS", "VHP");
Uplink::Send("PROTOCTL", "BIGLINES", "MLOCK", "MTAGS", "NEXTBANS", "VHP");
Uplink::Send("PROTOCTL", "EAUTH=" + Me->GetName() + ",,,Anope-" + Anope::VersionShort());
Uplink::Send("PROTOCTL", "SID=" + Me->GetSID());
@@ -345,7 +364,8 @@ private:
bool IsExtbanValid(const Anope::string &mask) override
{
return mask.length() >= 4 && mask[0] == '~' && mask[2] == ':';
Anope::string name, value;
return IsExtBan(mask, name, value);
}
void SendLogin(User *u, NickAlias *na) override
@@ -446,48 +466,61 @@ private:
}
};
class UnrealExtBan
: public ChannelModeVirtual<ChannelModeList>
namespace UnrealExtBan
{
char ext;
public:
UnrealExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
, ext(extban)
class Base
: public ChannelModeVirtual<ChannelModeList>
{
}
private:
char xbchar;
Anope::string xbname;
ChannelMode *Wrap(Anope::string &param) override
{
param = "~" + Anope::string(ext) + ":" + param;
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
}
public:
Base(const Anope::string &mname, const Anope::string& uname, char uchar)
: ChannelModeVirtual<ChannelModeList>(mname, "BAN")
, xbchar(uchar)
, xbname(uname)
{
}
ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) override
{
if (cm->type != MODE_LIST || param.length() < 4 || param[0] != '~' || param[1] != ext || param[2] != ':')
return cm;
ChannelMode *Wrap(Anope::string &param) override
{
auto prefix = Servers::Capab.count("NEXTBANS") ? xbname : Anope::string(xbchar);
param = Anope::printf("~%s:%s", prefix.c_str(), param.c_str());
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
}
param = param.substr(3);
return this;
}
};
ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) override
{
// The mask must be in the format ~<letter>:<value> or ~<name>:<value>.
if (cm->type != MODE_LIST)
return cm;
Anope::string name, value;
if (!IsExtBan(param, name, value))
return cm;
if (name.length() == 1 ? name[0] != xbchar : name != xbname)
return cm;
param = value;
return this;
}
};
namespace UnrealExtban
{
class ChannelMatcher final
: public UnrealExtBan
: public Base
{
public:
ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
ChannelMatcher()
: Base("CHANNELBAN", "channel", 'c')
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string channel = mask.substr(3);
auto channel = e->GetMask();
ChannelMode *cm = NULL;
if (channel[0] != '#')
{
@@ -512,137 +545,113 @@ namespace UnrealExtban
};
class EntryMatcher final
: public UnrealExtBan
: public Base
{
public:
EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
EntryMatcher(const Anope::string &mname, const Anope::string &uname, char uchar)
: Base(mname, uname, uchar)
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
return Entry(this->name, real_mask).Matches(u);
return Entry(this->base, e->GetMask()).Matches(u);
}
};
class RealnameMatcher final
: public UnrealExtBan
: public Base
{
public:
RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
RealnameMatcher()
: Base("REALNAMEBAN", "realname", 'r')
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
return Anope::Match(u->realname, real_mask);
}
};
class RegisteredMatcher final
: public UnrealExtBan
{
public:
RegisteredMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
return u->HasMode("REGISTERED") && mask.equals_ci(u->nick);
return Anope::Match(u->realname, e->GetMask());
}
};
class AccountMatcher final
: public UnrealExtBan
: public Base
{
public:
AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
AccountMatcher()
: Base("ACCOUNTBAN", "account", 'a')
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
if (real_mask == "0" && !u->Account()) /* ~a:0 is special and matches all unauthenticated users */
if (e->GetMask() == "0" && !u->Account()) /* ~a:0 is special and matches all unauthenticated users */
return true;
return u->Account() && Anope::Match(u->Account()->display, real_mask);
return u->Account() && Anope::Match(u->Account()->display, e->GetMask());
}
};
class FingerprintMatcher final
: public UnrealExtBan
: public Base
{
public:
FingerprintMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
FingerprintMatcher()
: Base("SSLBAN", "certfp", 'S')
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, e->GetMask());
}
};
class OperclassMatcher final
: public UnrealExtBan
: public Base
{
public:
OperclassMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
OperclassMatcher()
: Base("OPERCLASSBAN", "operclass", 'O')
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
ModData *moddata = u->GetExt<ModData>("ClientModData");
return moddata != NULL && moddata->find("operclass") != moddata->end() && Anope::Match((*moddata)["operclass"], real_mask);
return moddata != NULL && moddata->find("operclass") != moddata->end() && Anope::Match((*moddata)["operclass"], e->GetMask());
}
};
class TimedBanMatcher final
: public UnrealExtBan
: public Base
{
public:
TimedBanMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
TimedBanMatcher()
: Base("TIMEDBAN", "time", 't')
{
}
bool Matches(User *u, const Entry *e) override
{
/* strip down the time (~t:1234:) and call other matchers */
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
auto real_mask = e->GetMask();
real_mask = real_mask.substr(real_mask.find(":") + 1);
return Entry("BAN", real_mask).Matches(u);
}
};
class CountryMatcher final
: public UnrealExtBan
: public Base
{
public:
CountryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
CountryMatcher()
: Base("COUNTRYBAN", "country", 'C')
{
}
bool Matches(User *u, const Entry *e) override
{
const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
ModData *moddata = u->GetExt<ModData>("ClientModData");
if (moddata == NULL || moddata->find("geoip") == moddata->end())
return false;
@@ -652,7 +661,7 @@ namespace UnrealExtban
while (sep.GetToken(tokenbuf))
{
if (tokenbuf.rfind("cc=", 0) == 0)
return (tokenbuf.substr(3, 2) == real_mask);
return (tokenbuf.substr(3, 2) == e->GetMask());
}
return false;
}
@@ -838,17 +847,16 @@ struct IRCDMessageCapab final
case 'b':
ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
ModeManager::AddChannelMode(new UnrealExtban::ChannelMatcher("CHANNELBAN", "BAN", 'c'));
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("JOINBAN", "BAN", 'j'));
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("NONICKBAN", "BAN", 'n'));
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("QUIET", "BAN", 'q'));
ModeManager::AddChannelMode(new UnrealExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
ModeManager::AddChannelMode(new UnrealExtban::RegisteredMatcher("REGISTEREDBAN", "BAN", 'R'));
ModeManager::AddChannelMode(new UnrealExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'a'));
ModeManager::AddChannelMode(new UnrealExtban::FingerprintMatcher("SSLBAN", "BAN", 'S'));
ModeManager::AddChannelMode(new UnrealExtban::TimedBanMatcher("TIMEDBAN", "BAN", 't'));
ModeManager::AddChannelMode(new UnrealExtban::OperclassMatcher("OPERCLASSBAN", "BAN", 'O'));
ModeManager::AddChannelMode(new UnrealExtban::CountryMatcher("COUNTRYBAN", "BAN", 'C'));
ModeManager::AddChannelMode(new UnrealExtBan::ChannelMatcher());
ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("JOINBAN", "join", 'j'));
ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("NONICKBAN", "nickchange", 'n'));
ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("QUIET", "quiet", 'q'));
ModeManager::AddChannelMode(new UnrealExtBan::RealnameMatcher());
ModeManager::AddChannelMode(new UnrealExtBan::AccountMatcher());
ModeManager::AddChannelMode(new UnrealExtBan::FingerprintMatcher());
ModeManager::AddChannelMode(new UnrealExtBan::TimedBanMatcher());
ModeManager::AddChannelMode(new UnrealExtBan::OperclassMatcher());
ModeManager::AddChannelMode(new UnrealExtBan::CountryMatcher());
continue;
case 'e':
ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
@@ -1147,10 +1155,7 @@ struct IRCDMessageMode final
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
auto final_is_ts = server_ts && source.GetServer() != NULL;
Anope::string modes = params[1];
for (unsigned i = 2; i < params.size() - (final_is_ts ? 1 : 0); ++i)
modes += " " + params[i];
auto last_param = params.end() - (params.size() > 3 && final_is_ts ? 1 : 0);
if (IRCD->IsChannelValid(params[0]))
{
@@ -1158,7 +1163,7 @@ struct IRCDMessageMode final
auto ts = final_is_ts ? IRCD->ExtractTimestamp(params.back()) : 0;
if (c)
c->SetModesInternal(source, modes, ts);
c->SetModesInternal(source, params[1], { params.begin() + 2, last_param }, ts);
}
else
{
@@ -1420,11 +1425,12 @@ struct IRCDMessageSJoin final
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string modes;
std::vector<Anope::string> modeparams;
if (params.size() >= 4)
for (unsigned i = 2; i < params.size() - 1; ++i)
modes += " " + params[i];
if (!modes.empty())
modes.erase(modes.begin());
{
modes = params[2];
modeparams = { params.begin() + 3, params.end() };
}
std::list<Anope::string> bans, excepts, invites;
std::list<Message::Join::SJoinUser> users;
@@ -1474,7 +1480,7 @@ struct IRCDMessageSJoin final
}
auto ts = IRCD->ExtractTimestamp(params[0]);
Message::Join::SJoin(source, params[1], ts, modes, users);
Message::Join::SJoin(source, params[1], ts, modes, modeparams, users);
if (!bans.empty() || !excepts.empty() || !invites.empty())
{
+22 -4
View File
@@ -20,7 +20,11 @@
Serialize::Checker<botinfo_map> BotListByNick("BotInfo"), BotListByUID("BotInfo");
BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), Serializable("BotInfo"), channels("ChannelInfo"), botmodes(bmodes)
BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes)
: User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", {}, IRCD ? IRCD->UID_Retrieve() : "", NULL)
, Serializable("BotInfo")
, channels("ChannelInfo")
, botmodes(bmodes)
{
this->lastmsg = this->created = Anope::CurTime;
this->introduced = false;
@@ -35,9 +39,16 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A
// If we're synchronised with the uplink already, send the bot.
if (Me && Me->IsSynced())
{
Anope::string tmodes = !this->botmodes.empty() ? ("+" + this->botmodes) : IRCD->DefaultPseudoclientModes;
if (!tmodes.empty())
this->SetModesInternal(this, tmodes);
spacesepstream modesep(this->botmodes.empty() ? IRCD->DefaultPseudoclientModes : "+" + this->botmodes);
Anope::string modechars;
modesep.GetToken(modechars);
std::vector<Anope::string> modeparams;
modesep.GetTokens(modeparams);
if (!modechars.empty())
this->SetModesInternal(this, modechars, modeparams);
XLine x(this->nick, "Reserved for services");
IRCD->SendSQLine(NULL, &x);
@@ -254,6 +265,13 @@ CommandInfo *BotInfo::GetCommand(const Anope::string &cname)
return NULL;
}
Anope::string BotInfo::GetQueryCommand() const
{
if (Config->ServiceAlias && !this->alias.empty())
return Anope::printf("/%s", this->alias.c_str());
return Anope::printf("/msg %s", this->nick.c_str());
}
BotInfo *BotInfo::Find(const Anope::string &nick, bool nick_only)
{
if (!nick_only && IRCD != NULL && IRCD->RequiresID)
+13 -15
View File
@@ -611,13 +611,13 @@ void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const Anope::string &cmo
}
}
void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts, bool enforce_mlock)
void Channel::SetModesInternal(MessageSource &source, const Anope::string &modes, const std::vector<Anope::string> &params, time_t ts, bool enforce_mlock)
{
if (!ts)
;
else if (ts > this->creation_time)
{
Log(LOG_DEBUG) << "Dropping mode " << mode << " on " << this->name << ", " << ts << " > " << this->creation_time;
Log(LOG_DEBUG) << "Dropping mode " << modes << " on " << this->name << ", " << ts << " > " << this->creation_time;
return;
}
else if (ts < this->creation_time)
@@ -631,20 +631,18 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
/* Removing channel modes *may* delete this channel */
Reference<Channel> this_reference(this);
spacesepstream sep_modes(mode);
Anope::string m;
sep_modes.GetToken(m);
Anope::string modestring;
Anope::string paramstring;
int add = -1;
bool changed = false;
for (unsigned int i = 0, end = m.length(); i < end && this_reference; ++i)
auto paramit = params.begin();
for (const auto mchar : modes)
{
ChannelMode *cm;
if (!this_reference)
break;
switch (m[i])
ChannelMode *cm;
switch (mchar)
{
case '+':
modestring += '+';
@@ -657,10 +655,10 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
default:
if (add == -1)
continue;
cm = ModeManager::FindChannelModeByChar(m[i]);
cm = ModeManager::FindChannelModeByChar(mchar);
if (!cm)
{
Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << m[i];
Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << mchar;
continue;
}
modestring += cm->mchar;
@@ -686,9 +684,9 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
continue;
}
}
Anope::string token;
if (sep_modes.GetToken(token))
if (paramit != params.end())
{
auto token = *paramit++;
User *u = NULL;
if (cm->type == MODE_STATUS && (u = User::Find(token)))
paramstring += " " + u->nick;
@@ -703,7 +701,7 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
this->RemoveModeInternal(source, cm, token, enforce_mlock);
}
else
Log() << "warning: Channel::SetModesInternal() received more modes requiring params than params, modes: " << mode;
Log() << "warning: Channel::SetModesInternal() received more modes requiring params than params, modes: " << modes;
}
if (!this_reference)
+5 -5
View File
@@ -199,7 +199,7 @@ void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcomma
this->SendSyntax(source);
bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
if (has_help)
source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
source.Reply(MORE_INFO, source.service->GetQueryCommand().c_str(), source.command.c_str());
}
namespace
@@ -226,13 +226,13 @@ namespace
bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
if (has_help && similar.empty())
{
source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(),
Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
source.Reply(_("Unknown command \002%s\002. \"%s HELP\" for help."), message.c_str(),
source.service->GetQueryCommand().c_str());
}
else if (has_help)
{
source.Reply(_("Unknown command \002%s\002. Did you mean \002%s\002? \"%s%s HELP\" for help."),
message.c_str(), similar.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
source.Reply(_("Unknown command \002%s\002. Did you mean \002%s\002? \"%s HELP\" for help."),
message.c_str(), similar.c_str(), source.service->GetQueryCommand().c_str());
}
else if (similar.empty())
{
+6 -5
View File
@@ -121,7 +121,7 @@ template<typename T> static void ValidateNotZero(const Anope::string &block, con
Conf::Conf() : Block("")
{
ReadTimeout = 0;
UsePrivmsg = DefPrivmsg = false;
DefPrivmsg = false;
this->LoadConf(ServicesConf);
@@ -195,9 +195,7 @@ Conf::Conf() : Block("")
}
this->ReadTimeout = options->Get<time_t>("readtimeout");
this->UsePrivmsg = options->Get<bool>("useprivmsg");
this->UseStrictPrivmsg = options->Get<bool>("usestrictprivmsg");
this->StrictPrivmsg = !UseStrictPrivmsg ? "/msg " : "/";
this->ServiceAlias = options->Get<bool>("servicealias");
{
std::vector<Anope::string> defaults;
spacesepstream(this->GetModule("nickserv")->Get<const Anope::string>("defaults")).GetTokens(defaults);
@@ -339,7 +337,8 @@ Conf::Conf() : Block("")
&host = service->Get<const Anope::string>("host"),
&gecos = service->Get<const Anope::string>("gecos"),
&modes = service->Get<const Anope::string>("modes"),
&channels = service->Get<const Anope::string>("channels");
&channels = service->Get<const Anope::string>("channels"),
&alias = service->Get<const Anope::string>("alias", nick.upper());
ValidateNotEmptyOrSpaces("service", "nick", nick);
ValidateNotEmptyOrSpaces("service", "user", user);
@@ -350,6 +349,8 @@ Conf::Conf() : Block("")
BotInfo *bi = BotInfo::Find(nick, true);
if (!bi)
bi = new BotInfo(nick, user, host, gecos, modes);
bi->alias = alias;
bi->conf = true;
std::vector<Anope::string> oldchannels = bi->botchannels;
+2 -2
View File
@@ -337,7 +337,7 @@ bool Anope::Init(int ac, char **av)
Log(LOG_TERMINAL) << "-v, --version";
Log(LOG_TERMINAL) << "";
Log(LOG_TERMINAL) << "Further support is available from https://www.anope.org/";
Log(LOG_TERMINAL) << "Or visit us on IRC at irc.anope.org #anope";
Log(LOG_TERMINAL) << "Or visit us on IRC at irc.teranova.net #anope";
Anope::ReturnValue = EXIT_SUCCESS;
return false;
}
@@ -488,7 +488,7 @@ bool Anope::Init(int ac, char **av)
Log(LOG_TERMINAL) << "*** Support resources: Read through the anope.conf self-contained";
Log(LOG_TERMINAL) << "*** documentation. Read the documentation files found in the 'docs'";
Log(LOG_TERMINAL) << "*** folder. Visit our portal located at https://www.anope.org/. Join";
Log(LOG_TERMINAL) << "*** our support channel on /server irc.anope.org channel #anope.";
Log(LOG_TERMINAL) << "*** our support channel on /server irc.teranova.net channel #anope.";
throw CoreException("Configuration file failed to validate");
}
+1
View File
@@ -36,6 +36,7 @@ Mail::Message::~Message()
void Mail::Message::Run()
{
errno = 0;
auto *pipe = popen(sendmail_path.c_str(), "w");
if (!pipe)
{
+5 -19
View File
@@ -98,11 +98,11 @@ void Join::Run(MessageSource &source, const std::vector<Anope::string> &params,
users.emplace_back(ChannelStatus(), user);
Channel *chan = Channel::Find(channel);
SJoin(source, channel, chan ? chan->creation_time : Anope::CurTime, "", users);
SJoin(source, channel, chan ? chan->creation_time : Anope::CurTime, "", {}, users);
}
}
void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users)
void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::vector<Anope::string> &modeparams, const std::list<SJoinUser> &users)
{
bool created;
Channel *c = Channel::FindOrCreate(chan, created, ts ? ts : Anope::CurTime);
@@ -128,7 +128,7 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co
/* If we are syncing, mlock is checked later in Channel::Sync. It is important to not check it here
* so that Channel::SetCorrectModes can correctly detect the presence of channel mode +r.
*/
c->SetModesInternal(source, modes, ts, !c->syncing);
c->SetModesInternal(source, modes, modeparams, ts, !c->syncing);
for (const auto &[status, u] : users)
{
@@ -214,23 +214,19 @@ void Kill::Run(MessageSource &source, const std::vector<Anope::string> &params,
void Message::Mode::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
Anope::string buf;
for (unsigned i = 1; i < params.size(); ++i)
buf += " " + params[i];
if (IRCD->IsChannelValid(params[0]))
{
Channel *c = Channel::Find(params[0]);
if (c)
c->SetModesInternal(source, buf.substr(1), 0);
c->SetModesInternal(source, params[1], { params.begin() + 2, params.end() });
}
else
{
User *u = User::Find(params[0]);
if (u)
u->SetModesInternal(source, buf.substr(1));
u->SetModesInternal(source, params[1], { params.begin() + 2, params.end() });
}
}
@@ -328,18 +324,8 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &param
if (!servername.equals_ci(Me->GetName()))
return;
}
else if (!IRCD->RequiresID && Config->UseStrictPrivmsg)
{
BotInfo *bi = BotInfo::Find(receiver);
if (!bi)
return;
Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << u->nick;
u->SendMessage(bi, _("\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."), bi->nick.c_str(), bi->nick.c_str(), Me->GetName().c_str(), bi->nick.c_str());
return;
}
BotInfo *bi = BotInfo::Find(botname, nick_only);
if (bi)
{
Anope::string ctcpname, ctcpbody;
+1 -2
View File
@@ -835,8 +835,7 @@ bool Entry::Matches(User *u, bool full) const
if (cm != NULL && cm->type == MODE_LIST)
{
ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
if (cml->Matches(u, this))
return true;
return cml->Matches(u, this);
}
}
+9 -3
View File
@@ -50,9 +50,15 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano
/* Now do mode related stuff as we know what modes exist .. */
for (auto &[_, bi] : *BotListByNick)
{
Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : IRCD->DefaultPseudoclientModes;
spacesepstream modesep(bi->botmodes.empty() ? IRCD->DefaultPseudoclientModes : "+" + bi->botmodes);
bi->SetModesInternal(bi, modes);
Anope::string modechars;
modesep.GetToken(modechars);
std::vector<Anope::string> modeparams;
modesep.GetTokens(modeparams);
bi->SetModesInternal(bi, modechars, modeparams);
for (const auto &botchannel : bi->botchannels)
{
size_t h = botchannel.find('#');
@@ -322,7 +328,7 @@ bool Server::IsQuitting() const
void Server::Notice(BotInfo *source, const Anope::string &message)
{
if (Config->UsePrivmsg && Config->DefPrivmsg)
if (Config->DefPrivmsg)
IRCD->SendGlobalPrivmsg(source, this, message);
else
IRCD->SendGlobalNotice(source, this, message);
+7 -7
View File
@@ -24,8 +24,8 @@ die="yes"
###########################
# The GeoIP data is created by MaxMind, available from www.maxmind.com.
geoip_country_source="https://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip"
geoip_city_source="https://geolite.maxmind.com/download/geoip/database/GeoLiteCity_CSV/GeoLiteCity-latest.zip"
geoip_country_source="https://mirrors-cdn.liferay.com/geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip"
geoip_city_source="https://mirrors-cdn.liferay.com/geolite.maxmind.com/download/geoip/database/GeoLiteCity-latest.tar.xz"
geoip_region_source="https://www.maxmind.com/download/geoip/misc/region_codes.csv"
###########################
@@ -65,17 +65,17 @@ elif test $geoip_database = "city"; then
download "$geoip_city_source" "City Database:"
download "$geoip_region_source" "Region Database:"
echo "Unpacking..."
unzip -jo GeoLiteCity-latest.zip
rm GeoLiteCity-latest.zip
tar -xf GeoLiteCity-latest.tar.xz --strip-components 1
rm GeoLiteCity-latest.tar.xz
echo "Converting to utf-8..."
iconv -f ISO-8859-1 -t UTF-8 GeoLiteCity-Blocks.csv -o $prefix"geoip_city_blocks.csv"
iconv -f ISO-8859-1 -t UTF-8 GeoLiteCity-Location.csv -o $prefix"geoip_city_location.csv"
iconv -f ISO-8859-1 -t UTF-8 region.csv -o $prefix"geoip_city_region.csv"
rm GeoLiteCity-Blocks.csv GeoLiteCity-Location.csv region.csv
iconv -f ISO-8859-1 -t UTF-8 region_codes.csv -o $prefix"geoip_city_region.csv"
rm GeoLiteCity-Blocks.csv GeoLiteCity-Location.csv region_codes.csv
echo "Importing..."
mysqlimport --columns=start,end,locID --ignore-lines=2 $PARAMS $prefix"geoip_city_blocks.csv"
mysqlimport --columns=locID,country,region,city,@x,latitude,longitude,@x,areaCode --ignore-lines=2 $PARAMS $prefix"geoip_city_location.csv"
mysqlimport --columns=country,region,regionname $PARAMS $prefix"geoip_city_region.csv"
rm $prefix"geoip_city_blocks.csv" $prefix"geoip_city_location.csv" $prefix"geoip_city_region.csv" $prefix"geoip_country6.csv"
rm $prefix"geoip_city_blocks.csv" $prefix"geoip_city_location.csv" $prefix"geoip_city_region.csv"
echo "Done..."
fi
+14 -26
View File
@@ -31,7 +31,8 @@ time_t MaxUserTime = 0;
std::list<User *> User::quitting_users;
User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *account) : ip(uip)
User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const std::vector<Anope::string> &smodeparams, const Anope::string &suid, NickCore *account)
: ip(uip)
{
if (snick.empty() || sident.empty() || shost.empty())
throw CoreException("Bad args passed to User::User");
@@ -49,7 +50,7 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
this->server = sserver;
this->realname = srealname;
this->timestamp = this->signon = ts;
this->SetModesInternal(sserver, smodes);
this->SetModesInternal(sserver, smodes, smodeparams);
this->uid = suid;
this->super_admin = false;
this->nc = NULL;
@@ -110,7 +111,7 @@ static void Collide(User *u, const Anope::string &id, const Anope::string &type)
CollideKill(u, type);
}
User *User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc)
User *User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc, const std::vector<Anope::string> &smodeparams)
{
// How IRCds handle collisions varies a lot, for safety well just always kill both sides
// With properly set qlines, this can almost never happen anyway
@@ -132,7 +133,7 @@ User *User::OnIntroduce(const Anope::string &snick, const Anope::string &sident,
}
}
return new User(snick, sident, shost, svhost, sip, sserver, srealname, ts, smodes, suid, nc);
return new User(snick, sident, shost, svhost, sip, sserver, srealname, ts, smodes, smodeparams, suid, nc);
}
void User::ChangeNick(const Anope::string &newnick, time_t ts)
@@ -672,27 +673,14 @@ void User::SetModes(BotInfo *bi, const Anope::string &umodes)
}
}
void User::SetModesInternal(const MessageSource &source, const char *umodes, ...)
{
char buf[BUFSIZE] = "";
va_list args;
va_start(args, umodes);
vsnprintf(buf, BUFSIZE - 1, umodes, args);
va_end(args);
SetModesInternal(source, Anope::string(buf));
}
void User::SetModesInternal(const MessageSource &source, const Anope::string &umodes)
void User::SetModesInternal(const MessageSource &source, const Anope::string &umodes, const std::vector<Anope::string> &umodeparams)
{
if (this->server && this->server->IsSynced() && Anope::string(umodes) != "+")
Log(this, "mode") << "changes modes to " << umodes;
int add = -1;
Anope::string modebuf;
spacesepstream sep(umodes);
sep.GetToken(modebuf);
for (auto mode : modebuf)
auto paramit = umodeparams.begin();
for (const auto mode : umodes)
{
UserMode *um;
@@ -715,8 +703,8 @@ void User::SetModesInternal(const MessageSource &source, const Anope::string &um
if (add)
{
Anope::string sbuf;
if (um->type == MODE_PARAM && sep.GetToken(sbuf))
this->SetModeInternal(source, um, sbuf);
if (um->type == MODE_PARAM && paramit != umodeparams.end())
this->SetModeInternal(source, um, *paramit++);
else
this->SetModeInternal(source, um);
}
@@ -851,10 +839,10 @@ bool User::BadPassword()
bool User::ShouldPrivmsg() const
{
// Send a PRIVMSG instead of a NOTICE if:
// 1. options:useprivmsg is enabled.
// 2. The user is not registered and msg is in nickserv:defaults.
// 3. The user is registered and has set /ns set message on.
return Config->UsePrivmsg && ((!nc && Config->DefPrivmsg) || (nc && nc->HasExt("MSG")));
// 1. The user is not registered and msg is in nickserv:defaults.
// 2. The user is registered and has set /ns set message on.
static ExtensibleRef<bool> msg("MSG");
return (!nc && Config->DefPrivmsg) || (nc && msg && msg->HasExt(nc));
}
User *User::Find(const Anope::string &name, bool nick_only)
+1 -1
View File
@@ -2,5 +2,5 @@
VERSION_MAJOR=2
VERSION_MINOR=1
VERSION_PATCH=9
VERSION_PATCH=10
VERSION_EXTRA=""