mirror of
https://github.com/anope/anope.git
synced 2026-06-16 23:54:46 +02:00
Compare commits
229 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da799bd6f1 | |||
| 4dada51e08 | |||
| 1275fd01a7 | |||
| 5b8018eb80 | |||
| b2026fe739 | |||
| 3390d82ebe | |||
| 4762e306f9 | |||
| fd759f7bd3 | |||
| 003ddde09d | |||
| c021d7134e | |||
| a792088a62 | |||
| 03e2ebe2d2 | |||
| 0238f0a9e3 | |||
| c2dfb9a447 | |||
| bd8435a061 | |||
| 2cd67c9f36 | |||
| 45ab094d63 | |||
| 54389f474b | |||
| ac2b38b1b6 | |||
| df551bee03 | |||
| 59bb9d3d06 | |||
| 3b2d798e76 | |||
| ff6d6bdb3c | |||
| 411b3ce65a | |||
| ad19603818 | |||
| 535ff9b839 | |||
| 51916a50d2 | |||
| 42e58952cc | |||
| ba9f4e93c2 | |||
| 679a313ae2 | |||
| 390975e6c4 | |||
| d631885495 | |||
| 8e337c6592 | |||
| 9d89d8233d | |||
| 6f27418381 | |||
| 1932081c27 | |||
| f73159159f | |||
| eccb338cdd | |||
| 4021c0bb68 | |||
| 7dfb40cb58 | |||
| 0fbd3095c4 | |||
| 6d426ec386 | |||
| 1b33a51695 | |||
| 168a1173ed | |||
| 59c777d4ff | |||
| 43f88524e2 | |||
| 04de41ad7f | |||
| dd13846cad | |||
| 6864bc6171 | |||
| 003cb55409 | |||
| d15b8ee949 | |||
| 70de2b7de2 | |||
| e5c5689985 | |||
| 928d4260dc | |||
| 5e8561a7f1 | |||
| 4dd3075ddf | |||
| dbef7a7c64 | |||
| cd0f00a819 | |||
| b2d40d4189 | |||
| e6e812c43c | |||
| 2dbd41d244 | |||
| 02aeb254ee | |||
| 1245b43ade | |||
| 5a3f9f3f87 | |||
| 2c6f4d7c27 | |||
| 64f8449bf4 | |||
| 0e1f6b403b | |||
| 206192abdc | |||
| 32d3ddc0e4 | |||
| 4410e5ccce | |||
| d5f2232140 | |||
| 6d754b7d73 | |||
| 4d2870fa45 | |||
| 5948c2ea53 | |||
| ace7d99797 | |||
| 52595b90fa | |||
| b39f002d1b | |||
| 5df95d9f86 | |||
| a56d9a4096 | |||
| ce7bb15c18 | |||
| 6873630f2e | |||
| 44a4d62654 | |||
| 97389cd105 | |||
| 80c0adf7c8 | |||
| 6a539277b9 | |||
| 9930fa01ac | |||
| 40929a0490 | |||
| 783be31f64 | |||
| 0f5f2aef2e | |||
| 6cc997c4e9 | |||
| eda6d8cc0f | |||
| 3440b38a21 | |||
| fca421aa2a | |||
| 035905d321 | |||
| d1cd57d98e | |||
| 48daeeac1d | |||
| 9bcf46f8ea | |||
| 0b6c7ce5d6 | |||
| a0d21b207b | |||
| 3cc5b5143f | |||
| da738126a4 | |||
| 0bb1bc5c67 | |||
| 72010cd1a9 | |||
| c48b3af3d4 | |||
| 85c129701b | |||
| a9e5a79e91 | |||
| adc1343d6c | |||
| 8aa1102c7a | |||
| 1a89d32926 | |||
| ad06853edf | |||
| 66ae20e0f2 | |||
| 2850e3c65c | |||
| 80b8856254 | |||
| 21c8164539 | |||
| a4abd27ffd | |||
| b912b403f0 | |||
| 59e9d47667 | |||
| 1108e54250 | |||
| 8b37cdb5d5 | |||
| c5bff3a099 | |||
| 61b0c82884 | |||
| c4c159d197 | |||
| 04a32be1e1 | |||
| fe4b8ee669 | |||
| 34b451f36c | |||
| 16aff210fd | |||
| 5702fb9145 | |||
| 783ba3fd74 | |||
| f1ddd7cd02 | |||
| c424c4d24d | |||
| 2d88383d9e | |||
| c73a6c621f | |||
| 96a503b4d9 | |||
| 0632abd111 | |||
| 1043e2189c | |||
| 85f0d56c39 | |||
| cebc3f757b | |||
| 447a59d6f5 | |||
| 75aa633d87 | |||
| 7833a96dde | |||
| d326f869a3 | |||
| b724617a8d | |||
| 76f0c78ece | |||
| 13491bd960 | |||
| bade5ea109 | |||
| 682a6a6ad4 | |||
| 50030e07fa | |||
| 7b2f0f5790 | |||
| 23e72fc934 | |||
| e182519e4d | |||
| 4317b5557e | |||
| f97448f48a | |||
| cb334fbae1 | |||
| d3bb930a5e | |||
| 0fc1eb3133 | |||
| 0ac9d70d63 | |||
| a3d61e3d18 | |||
| cac10aaa41 | |||
| be5a0e8108 | |||
| 3da8244de5 | |||
| 8722daa6e7 | |||
| a0e98acea8 | |||
| c5a2f40666 | |||
| 1daafff79d | |||
| 3dd20975aa | |||
| 368d8e8b1c | |||
| 7c5d2c09fa | |||
| 41e702d853 | |||
| 19f83eaa34 | |||
| b1212f9e89 | |||
| 3e9f516d55 | |||
| 744b8bc4dc | |||
| e9a0a214b0 | |||
| 46c5570b1d | |||
| 151795a1df | |||
| 50f17ea8e1 | |||
| 2609ff44c6 | |||
| ca30bb2370 | |||
| f36b311f84 | |||
| fec85376e7 | |||
| 0bf14650fa | |||
| 49f93b7670 | |||
| ce0982cc4a | |||
| b4150841ec | |||
| eec428b0c7 | |||
| b706a6259e | |||
| 2cf8f003ce | |||
| 07f57b1108 | |||
| 5d648f9f1c | |||
| 46e6b0adde | |||
| 977780d8ef | |||
| 459f3d07c9 | |||
| b76b407b33 | |||
| 8b089ab1a7 | |||
| fbec4d04a5 | |||
| 34582a40ef | |||
| 4b15ca0232 | |||
| 997302f861 | |||
| b3b6e9f862 | |||
| d23bfb0113 | |||
| 0b7b4aa42d | |||
| fab8589e1e | |||
| 937404e311 | |||
| c5ad774ce5 | |||
| 1321f4f071 | |||
| 4319b6428f | |||
| e1f6d0ca16 | |||
| bb9074cbd5 | |||
| 72f5e3580f | |||
| 4b854d3935 | |||
| 0b2b00b37d | |||
| 196a3c32c2 | |||
| 8955c53088 | |||
| 88c71fba64 | |||
| 21f61981ca | |||
| 5752c07a56 | |||
| 010beb52b1 | |||
| c955941413 | |||
| 2e2515b9f0 | |||
| f0b26c9b44 | |||
| f953f7f006 | |||
| 84baf15620 | |||
| 89f61ac91b | |||
| b091184c60 | |||
| 6b1a491694 | |||
| 66d3293ae6 | |||
| a4691f9d4d | |||
| 51c7a15c45 | |||
| 151f9c2bcc |
@@ -13,7 +13,7 @@ jobs:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
CXXFLAGS: -Werror
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
CXXFLAGS: -Werror
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
CONAN_USER_HOME: ${{ github.workspace }}/win/build
|
||||
CONAN_USER_HOME_SHORT: None
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Setup NSIS
|
||||
run: |-
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- name: Setup Conan
|
||||
uses: turtlebrowser/get-conan@v1.2
|
||||
with:
|
||||
version: 1.64.0
|
||||
version: 1.66.0
|
||||
|
||||
- name: Try to restore libraries from the cache
|
||||
uses: actions/cache/restore@v4
|
||||
|
||||
@@ -13,14 +13,6 @@
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
exists () { # because some shells don't have test -e
|
||||
if [ -f $1 -o -d $1 -o -p $1 -o -c $1 -o -b $1 ] ; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
Load_Cache () {
|
||||
if [ -f $SOURCE_DIR/config.cache -a -r $SOURCE_DIR/config.cache -a ! "$IGNORE_CACHE" ] ; then
|
||||
echo "Using defaults from config.cache. To ignore, $SOURCE_DIR/Config -nocache"
|
||||
@@ -208,7 +200,7 @@ while [ $ok -eq 0 ] ; do
|
||||
INPUT=$INSTDIR
|
||||
fi
|
||||
if [ ! -d "$INPUT" ] ; then
|
||||
if exists "$INPUT" ; then
|
||||
if [ -e "$INPUT" ]; then
|
||||
echo "$INPUT exists, but is not a directory!"
|
||||
else
|
||||
echo "$INPUT does not exist. Create it?"
|
||||
@@ -220,7 +212,7 @@ while [ $ok -eq 0 ] ; do
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
elif exists "$INPUT/include/services.h" ; then
|
||||
elif [ -e "$INPUT/include/services.h" ]; then
|
||||
echo "You cannot use the Anope source directory as a target directory."
|
||||
else
|
||||
ok=1
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 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)
|
||||
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)
|
||||
install(FILES ${DATA}
|
||||
DESTINATION ${CONF_DIR}
|
||||
)
|
||||
|
||||
+76
-134
@@ -65,10 +65,6 @@
|
||||
* will typically be disabled. If this is not the case, more
|
||||
* information will be given in the documentation.
|
||||
*
|
||||
* [DISCOURAGED]
|
||||
* Indicates a directive which may cause undesirable side effects if
|
||||
* specified.
|
||||
*
|
||||
* [DEPRECATED]
|
||||
* Indicates a directive which will disappear in a future version of
|
||||
* Anope, usually because its functionality has been either
|
||||
@@ -87,8 +83,9 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
* The "services.host" define is used in multiple different locations throughout
|
||||
* the configuration for the server name and pseudoclient hostnames. You should
|
||||
* change the value to the hostname you wish to use for your services server.
|
||||
*/
|
||||
define
|
||||
{
|
||||
@@ -259,7 +256,6 @@ serverinfo
|
||||
* You MUST modify this to match the IRCd you run.
|
||||
*
|
||||
* Supported:
|
||||
* - bahamut
|
||||
* - hybrid
|
||||
* - inspircd
|
||||
* - ngircd
|
||||
@@ -326,7 +322,7 @@ networkinfo
|
||||
* The characters allowed in hostnames. This is used for validating hostnames given
|
||||
* to services, such as BotServ bot hostnames and user vhosts. Changing this is not
|
||||
* recommended unless you know for sure your IRCd supports whatever characters you are
|
||||
* wanting to use. Telling services to set a vHost containing characters your IRCd
|
||||
* wanting to use. Telling services to set a vhost containing characters your IRCd
|
||||
* disallows could potentially break the IRCd and/or Anope.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
@@ -334,21 +330,21 @@ networkinfo
|
||||
vhost_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-/"
|
||||
|
||||
/*
|
||||
* If set to true, allows vHosts to not contain dots (.).
|
||||
* If enabled, allows vhosts to not contain dots (.).
|
||||
* Newer IRCds generally do not have a problem with this, but the same warning as
|
||||
* vhost_chars applies.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
allow_undotted_vhosts = false
|
||||
allow_undotted_vhosts = no
|
||||
|
||||
/*
|
||||
* The characters that are not allowed to be at the very beginning or very ending
|
||||
* of a vHost. The same warning as vhost_chars applies.
|
||||
* of a vhost. The same warning as vhost_chars applies.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
disallow_start_or_end = ".-"
|
||||
disallow_start_or_end = ".-/"
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -588,7 +584,7 @@ include
|
||||
}
|
||||
|
||||
/*
|
||||
* [OPTIONAL] NickServ
|
||||
* [RECOMMENDED] NickServ
|
||||
*
|
||||
* Includes nickserv.example.conf, which is necessary for NickServ functionality.
|
||||
*
|
||||
@@ -746,11 +742,13 @@ log
|
||||
* nickserv/alist - Can see the channel access list of other users
|
||||
* nickserv/auspex - Can see any information with /NICKSERV INFO
|
||||
* nickserv/cert - Can modify other users certificate lists
|
||||
* nickserv/confirm - Can confirm other users nicknames
|
||||
* nickserv/confirm/email - Can confirm other users email address change
|
||||
* nickserv/confirm/register - Can confirm other users account registration
|
||||
* nickserv/drop - Can drop other users nicks
|
||||
* nickserv/drop/display - Allows dropping display nicks when preservedisplay is enabled
|
||||
* nickserv/drop/override - Allows dropping nicks without using a confirmation code
|
||||
* nickserv/recover - Can recover other users nicks
|
||||
* nickserv/resend - Can resend confirmation codes via email
|
||||
* operserv/config - Can modify services's configuration
|
||||
* operserv/oper/modify - Can add and remove operators with at most the same privileges
|
||||
* protected - Can not be kicked from channels by services
|
||||
@@ -815,10 +813,10 @@ opertype
|
||||
inherits = "Helper, Another Helper"
|
||||
|
||||
/* What commands (see above) this opertype may use */
|
||||
commands = "chanserv/list chanserv/suspend chanserv/topic memoserv/staff nickserv/list nickserv/suspend operserv/mode operserv/chankill operserv/akill operserv/session operserv/modinfo operserv/sqline operserv/oper operserv/kick operserv/ignore operserv/snline"
|
||||
commands = "chanserv/list chanserv/suspend chanserv/topic memoserv/staff nickserv/list nickserv/resend nickserv/suspend operserv/mode operserv/chankill operserv/akill operserv/session operserv/modinfo operserv/sqline operserv/oper operserv/kick operserv/ignore operserv/snline"
|
||||
|
||||
/* What privs (see above) this opertype has */
|
||||
privs = "chanserv/auspex chanserv/no-register-limit memoserv/* nickserv/auspex nickserv/confirm"
|
||||
privs = "chanserv/auspex chanserv/no-register-limit memoserv/* nickserv/auspex nickserv/confirm/*"
|
||||
|
||||
/*
|
||||
* Modes to be set on users when they identify to accounts linked to this opertype.
|
||||
@@ -891,8 +889,8 @@ opertype
|
||||
/* An optional list of user@host masks. If defined the user must be connected from one of them */
|
||||
#host = "*@*.anope.org ident@*"
|
||||
|
||||
/* An optional vHost to set on users who identify for this oper block.
|
||||
* This will override HostServ vHosts, and may not be available on all IRCds
|
||||
/* An optional vhost to set on users who identify for this oper block.
|
||||
* This will override HostServ vhosts, and may not be available on all IRCds
|
||||
*/
|
||||
#vhost = "oper.mynet"
|
||||
}
|
||||
@@ -931,18 +929,20 @@ mail
|
||||
usemail = yes
|
||||
|
||||
/*
|
||||
* This is the command-line that will be used to call the mailer to send an
|
||||
* email. It must be called with all the parameters needed to make it
|
||||
* scan the mail input to find the mail recipient; consult your mailer
|
||||
* documentation.
|
||||
* The command used for sending emails. It is assumed that this behaves like
|
||||
* sendmail (i.e. it reads the email from the standard input stream) but you
|
||||
* should probably use Postfix or some other sendmail-compatible emailer
|
||||
* instead of sendmail as sendmail is very hard to configure correctly. If
|
||||
* you are using Windows then https://www.glob.com.au/sendmail/ is probably
|
||||
* the best option currently.
|
||||
*
|
||||
* Postfix users must use the compatible sendmail utility provided with
|
||||
* it. This one usually needs no parameters on the command-line. Most
|
||||
* sendmail applications (or replacements of it) require the -t option
|
||||
* to be used.
|
||||
*
|
||||
* If you are running on Windows you should use a Windows sendmail port
|
||||
* like https://www.glob.com.au/sendmail/ for sending emails.
|
||||
* If your emailer sends emails directly from the services host you will
|
||||
* need to configure DKIM, DMARC, and SPF to avoid email hosts from marking
|
||||
* your services emails as spam. It is important that you do this *BEFORE*
|
||||
* sending emails for the first time as some email providers will add your
|
||||
* host to a DNSBL like Spamhaus if they consider your emails to be spam. If
|
||||
* this is too difficult then you may want to consider sending emails via an
|
||||
* external email provider using a forwarder like msmtp.
|
||||
*/
|
||||
#sendmailpath = "/usr/sbin/sendmail -it"
|
||||
|
||||
@@ -993,7 +993,7 @@ mail
|
||||
registration_message = "Hi,
|
||||
|
||||
You have requested to register the nickname {nick} on {network}.
|
||||
Please type \" /msg NickServ CONFIRM {code} \" to complete registration.
|
||||
Please type \" /msg NickServ CONFIRM REGISTER {code} \" to complete registration.
|
||||
|
||||
If you don't know why this mail was sent to you, please ignore it silently.
|
||||
|
||||
@@ -1011,7 +1011,7 @@ mail
|
||||
reset_message = "Hi,
|
||||
|
||||
You have requested to have the password for {nick} reset.
|
||||
To reset your password, type \" /msg NickServ CONFIRM {nick} {code} \"
|
||||
To reset your password, type \" /msg NickServ CONFIRM RESETPASS {nick} {code} \"
|
||||
|
||||
If you don't know why this mail was sent to you, please ignore it silently.
|
||||
|
||||
@@ -1031,7 +1031,7 @@ mail
|
||||
emailchange_message = "Hi,
|
||||
|
||||
You have requested to change your email address from {old_email} to {new_email}.
|
||||
Please type \" /msg NickServ CONFIRM {code} \" to confirm this change.
|
||||
Please type \" /msg NickServ CONFIRM EMAIL {code} \" to confirm this change.
|
||||
|
||||
If you don't know why this mail was sent to you, please ignore it silently.
|
||||
|
||||
@@ -1065,96 +1065,46 @@ mail
|
||||
* have will not be stored!
|
||||
*/
|
||||
|
||||
/*
|
||||
* [DEPRECATED] db_old
|
||||
*
|
||||
* This is the old binary database format from late Anope 1.7.x, Anope 1.8.x, and
|
||||
* early Anope 1.9.x. This module only loads these databases, and will NOT save them.
|
||||
* You should only use this to upgrade old databases to a newer database format by loading
|
||||
* other database modules in addition to this one, which will be used when saving databases.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_old"
|
||||
|
||||
/*
|
||||
* This is the encryption type used by the databases. This must be set correctly or
|
||||
* your passwords will not work. Valid options are: md5, oldmd5, sha1, and plain.
|
||||
* You must also be sure to load the correct encryption module below in the Encryption
|
||||
* Modules section so that your passwords work.
|
||||
*/
|
||||
#hash = "md5"
|
||||
}
|
||||
|
||||
/*
|
||||
* db_atheme
|
||||
*
|
||||
* This allows importing databases from Atheme. You should load another database module as
|
||||
* well as this as it can only read Atheme databases not write them.
|
||||
* This allows importing databases from Atheme. You should load another database
|
||||
* module like db_json as well as this as it can only read Atheme databases not
|
||||
* write them.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_atheme"
|
||||
|
||||
/*
|
||||
* The database name db_atheme should use.
|
||||
* The file that db_atheme will import your main database from.
|
||||
*/
|
||||
database = "atheme.db"
|
||||
}
|
||||
|
||||
/*
|
||||
* [RECOMMENDED] db_flatfile
|
||||
* [DEPRECATED] db_flatfile
|
||||
*
|
||||
* This is the default flatfile database format.
|
||||
* This allows importing databases from the custom flat file format used between
|
||||
* Anope 1.9.6 and 2.1.17. You should load another database module like db_json
|
||||
* as well as this as it can only read db_flatfile databases not write them.
|
||||
*/
|
||||
module
|
||||
#module
|
||||
{
|
||||
name = "db_flatfile"
|
||||
|
||||
/*
|
||||
* The database name db_flatfile should use
|
||||
* The file that db_flatfile will import your main database from.
|
||||
*/
|
||||
database = "anope.db"
|
||||
|
||||
/*
|
||||
* Sets the number of days backups of databases are kept. If you don't give it,
|
||||
* or if you set it to 0, Anope won't backup the databases.
|
||||
*
|
||||
* This directive is optional, but recommended.
|
||||
*/
|
||||
keepbackups = 7
|
||||
|
||||
/*
|
||||
* Allows Anope to continue file write operations (i.e. database saving)
|
||||
* even if the original file cannot be backed up. Enabling this option may
|
||||
* allow Anope to continue operation under conditions where it might
|
||||
* otherwise fail, such as a nearly-full disk.
|
||||
*
|
||||
* NOTE: Enabling this option can cause irrecoverable data loss under some
|
||||
* conditions, so make CERTAIN you know what you're doing when you enable it!
|
||||
*
|
||||
* This directive is optional, and you are discouraged against enabling it.
|
||||
*/
|
||||
#nobackupokay = yes
|
||||
|
||||
/*
|
||||
* If enabled, services will fork a child process to save databases.
|
||||
*
|
||||
* This is only useful with very large databases, with hundreds
|
||||
* of thousands of objects, that have a noticeable delay from
|
||||
* writing databases.
|
||||
*/
|
||||
fork = no
|
||||
}
|
||||
|
||||
/*
|
||||
* db_json
|
||||
* [RECOMMENDED] db_json
|
||||
*
|
||||
* Stores your data in a JSON file. This is currently experimental and has not
|
||||
* been fully tested so make sure you have db_flatfile loaded as a secondary
|
||||
* database module if you use this.
|
||||
* Stores your database in a JSON file.
|
||||
*/
|
||||
#module
|
||||
module
|
||||
{
|
||||
name = "db_json"
|
||||
|
||||
@@ -1203,17 +1153,21 @@ module
|
||||
/*
|
||||
* db_sql and db_sql_live
|
||||
*
|
||||
* db_sql module allows saving and loading databases using one of the SQL engines.
|
||||
* This module loads the databases once on startup, then incrementally updates
|
||||
* objects in the database as they are changed within Anope in real time. Changes
|
||||
* to the SQL tables not done by Anope will have no effect and will be overwritten.
|
||||
* Allows saving and loading databases to a SQL database.
|
||||
*
|
||||
* db_sql_live module allows saving and loading databases using one of the SQL engines.
|
||||
* This module reads and writes to SQL in real time. Changes to the SQL tables
|
||||
* will be immediately reflected into Anope. This module should not be loaded
|
||||
* in conjunction with db_sql. It should also not be used on large networks as it
|
||||
* executes quite a lot of queries which can cause performance issues.
|
||||
* db_sql loads the databases once on startup and then incrementally updates in
|
||||
* in the database as they are changed within Anope. Changes to the SQL tables
|
||||
* not done by Anope will have no effect and will be overwritten.
|
||||
*
|
||||
* db_sql_live module reads and writes to SQL in real time. Changes to the SQL
|
||||
* tables will be immediately reflected in Anope. This module can not be loaded
|
||||
* at the same time as db_sql. It should also not be used on large networks as
|
||||
* it executes quite a lot of queries which can cause performance issues.
|
||||
*
|
||||
* IMPORTANT: The SQL schema has changed in the 2.1 branch. Whilst Anope will
|
||||
* try to update your schema it is recommended that before upgrading you export
|
||||
* to a file and re-import your database on 2.1. This will remove any obsolete
|
||||
* columns and change the types of existing columns to match the new schema.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
@@ -1221,10 +1175,10 @@ module
|
||||
#name = "db_sql_live"
|
||||
|
||||
/*
|
||||
* The SQL service db_sql(_live) should use, these are configured in modules.conf.
|
||||
* For MySQL, this should probably be mysql/main.
|
||||
* The SQL service that db_sql(_live) should use. These are configured in
|
||||
* modules.example.conf. For MySQL, this should probably be mysql/main.
|
||||
*/
|
||||
engine = "sqlite/main"
|
||||
engine = "mysql/main"
|
||||
|
||||
/*
|
||||
* An optional prefix to prepended to the name of each created table.
|
||||
@@ -1232,18 +1186,22 @@ module
|
||||
*/
|
||||
#prefix = "anope_db_"
|
||||
|
||||
/* Whether or not to import data from another database module in to SQL on startup.
|
||||
* If you enable this, be sure that the database services is configured to use is
|
||||
* empty and that another database module to import from is loaded BEFORE db_sql.
|
||||
* After you enable this and do a database import you MUST disable it for
|
||||
* subsequent restarts. If you want to keep writing a flatfile database after the
|
||||
* SQL import is done you should load db_flatfile AFTER this module.
|
||||
/*
|
||||
* Whether or not to import data from another database module in to SQL on
|
||||
* startup.
|
||||
*
|
||||
* Note that you can not import databases using db_sql_live. If you want to import
|
||||
* databases and use db_sql_live you should import them using db_sql, then shut down
|
||||
* and start services with db_sql_live.
|
||||
* If you enable this, be sure that the database Anope is configured to use
|
||||
* is empty and that another database module to import from is loaded BEFORE
|
||||
* db_sql. After you enable this and do a database import you MUST disable
|
||||
* it for subsequent restarts. If you want to keep writing a file database
|
||||
* after the SQL import is done you should load db_flatfile or db_json AFTER
|
||||
* this module.
|
||||
*
|
||||
* Note that you can not import databases using db_sql_live. If you want to
|
||||
* import databases and use db_sql_live you should import them using db_sql,
|
||||
* then shut down and start Anope with db_sql_live.
|
||||
*/
|
||||
import = false
|
||||
import = no
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1362,7 +1320,7 @@ module
|
||||
#module { name = "enc_posix" }
|
||||
|
||||
/*
|
||||
* [DEPRECATED] enc_md5, enc_none, enc_old, enc_sha1, enc_sha256
|
||||
* [DEPRECATED] enc_md5, enc_none, enc_sha1, enc_sha256
|
||||
*
|
||||
* Provides verify-only support for passwords encrypted using encryption methods
|
||||
* from older versions of Anope. These methods are no longer considered secure
|
||||
@@ -1372,8 +1330,6 @@ module
|
||||
* enc_md5: Verifies passwords encrypted with the MD5 algorithm
|
||||
* enc_none: Verifies passwords that are not encrypted
|
||||
* enc_sha1: Verifies passwords encrypted with the SHA1 algorithm
|
||||
* enc_old: Verifies passwords encrypted with the broken MD5 algorithm used
|
||||
* before 1.7.17.
|
||||
* enc_sha256: Verifies passwords encrypted with the SHA256 algorithm using a
|
||||
* custom initialisation vector as a salt.
|
||||
*
|
||||
@@ -1382,7 +1338,6 @@ module
|
||||
*/
|
||||
#module { name = "enc_md5" }
|
||||
#module { name = "enc_none" }
|
||||
#module { name = "enc_old" }
|
||||
#module { name = "enc_sha1" }
|
||||
#module { name = "enc_sha256" }
|
||||
|
||||
@@ -1402,16 +1357,3 @@ include
|
||||
type = "file"
|
||||
name = "chanstats.example.conf"
|
||||
}
|
||||
|
||||
/*
|
||||
* IRC2SQL Gateway
|
||||
* This module collects data about users, channels and servers. It doesn't build stats
|
||||
* itself, however, it gives you the database, it's up to you how you use it.
|
||||
*
|
||||
* Requires a MySQL Database and MySQL version 5.5 or higher
|
||||
*/
|
||||
#include
|
||||
{
|
||||
type = "file"
|
||||
name = "irc2sql.example.conf"
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ service
|
||||
/*
|
||||
* The realname of the BotServ client.
|
||||
*/
|
||||
gecos = "Bot Service"
|
||||
real = "Bot Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
@@ -296,11 +296,9 @@ command { service = "BotServ"; name = "KICK ITALICS"; command = "botserv/kick/it
|
||||
command { service = "BotServ"; name = "KICK REPEAT"; command = "botserv/kick/repeat"; }
|
||||
command { service = "BotServ"; name = "KICK REVERSES"; command = "botserv/kick/reverses"; }
|
||||
command { service = "BotServ"; name = "KICK UNDERLINES"; command = "botserv/kick/underlines"; }
|
||||
|
||||
command { service = "BotServ"; name = "SET DONTKICKOPS"; command = "botserv/set/dontkickops"; }
|
||||
command { service = "BotServ"; name = "SET DONTKICKVOICES"; command = "botserv/set/dontkickvoices"; }
|
||||
|
||||
|
||||
/*
|
||||
* bs_set
|
||||
*
|
||||
@@ -341,7 +339,6 @@ privilege
|
||||
xop = "AOP"
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fantasy
|
||||
*
|
||||
@@ -387,15 +384,15 @@ fantasy { name = "ENFORCE"; command = "chanserv/enforce"; }
|
||||
fantasy { name = "ENTRYMSG"; command = "chanserv/entrymsg"; }
|
||||
fantasy { name = "FLAGS"; command = "chanserv/flags"; }
|
||||
fantasy { name = "HALFOP"; command = "chanserv/modes"; }
|
||||
fantasy { name = "HELP"; command = "generic/help"; prepend_channel = false; }
|
||||
fantasy { name = "HELP"; command = "generic/help"; prepend_channel = no; require_privilege = no; }
|
||||
fantasy { name = "HOP"; command = "chanserv/xop"; }
|
||||
fantasy { name = "INFO"; command = "chanserv/info"; prepend_channel = false; }
|
||||
fantasy { name = "INFO"; command = "chanserv/info"; prepend_channel = no; }
|
||||
fantasy { name = "INVITE"; command = "chanserv/invite"; }
|
||||
fantasy { name = "K"; command = "chanserv/kick"; }
|
||||
fantasy { name = "KB"; command = "chanserv/ban"; }
|
||||
fantasy { name = "KICK"; command = "chanserv/kick"; }
|
||||
fantasy { name = "LEVELS"; command = "chanserv/levels"; }
|
||||
fantasy { name = "LIST"; command = "chanserv/list"; prepend_channel = false; }
|
||||
fantasy { name = "LIST"; command = "chanserv/list"; prepend_channel = no; }
|
||||
fantasy { name = "LOG"; command = "chanserv/log"; }
|
||||
fantasy { name = "MODE"; command = "chanserv/mode"; }
|
||||
fantasy { name = "MUTE"; command = "chanserv/ban"; kick = no; mode = "QUIET"; }
|
||||
@@ -403,7 +400,7 @@ fantasy { name = "OP"; command = "chanserv/modes"; }
|
||||
fantasy { name = "OWNER"; command = "chanserv/modes"; }
|
||||
fantasy { name = "PROTECT"; command = "chanserv/modes"; }
|
||||
fantasy { name = "QOP"; command = "chanserv/xop"; }
|
||||
fantasy { name = "SEEN"; command = "chanserv/seen"; prepend_channel = false; }
|
||||
fantasy { name = "SEEN"; command = "chanserv/seen"; prepend_channel = no; }
|
||||
fantasy { name = "SOP"; command = "chanserv/xop"; }
|
||||
fantasy { name = "STATUS"; command = "chanserv/status"; }
|
||||
fantasy { name = "SUSPEND"; command = "chanserv/suspend"; permission = "chanserv/suspend"; }
|
||||
|
||||
+18
-28
@@ -26,7 +26,7 @@ service
|
||||
/*
|
||||
* The realname of the ChanServ client.
|
||||
*/
|
||||
gecos = "Channel Registration Service"
|
||||
real = "Channel Registration Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
@@ -100,6 +100,7 @@ module
|
||||
* not in use.
|
||||
* - cs_no_expire: Enables no expire. Needs founder, successor (if set) or anyone in the access list
|
||||
* to be a registered nick, otherwise the channel will be dropped.
|
||||
* - cs_stats: Enable Chanstats for newly registered channels
|
||||
* - none: No defaults
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to cs_keep_modes, keeptopic, peace,
|
||||
@@ -171,19 +172,19 @@ module
|
||||
/*
|
||||
* If set, prevents channel access entries from containing hostmasks.
|
||||
*/
|
||||
disallow_hostmask_access = false
|
||||
disallow_hostmask_access = no
|
||||
|
||||
/*
|
||||
* If set, prevents channels from being on access lists.
|
||||
*/
|
||||
disallow_channel_access = false
|
||||
disallow_channel_access = no
|
||||
|
||||
/*
|
||||
* If set, ChanServ will always lower the timestamp of registered channels to their registration date.
|
||||
* This prevents several race conditions where unauthorized users can join empty registered channels and set
|
||||
* modes etc. prior to services deopping them.
|
||||
*/
|
||||
always_lower_ts = false
|
||||
always_lower_ts = no
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -946,7 +947,7 @@ command { service = "ChanServ"; name = "AKICK"; command = "chanserv/akick"; grou
|
||||
* Used for banning users from channels.
|
||||
*/
|
||||
module { name = "cs_ban" }
|
||||
command { service = "ChanServ"; name = "BAN"; command = "chanserv/ban"; }
|
||||
command { service = "ChanServ"; name = "BAN"; command = "chanserv/ban"; group = "chanserv/management"; }
|
||||
|
||||
/*
|
||||
* cs_clone
|
||||
@@ -1047,7 +1048,7 @@ command { service = "ChanServ"; name = "INVITE"; command = "chanserv/invite"; }
|
||||
* Used for kicking users from channels.
|
||||
*/
|
||||
module { name = "cs_kick" }
|
||||
command { service = "ChanServ"; name = "KICK"; command = "chanserv/kick"; }
|
||||
command { service = "ChanServ"; name = "KICK"; command = "chanserv/kick"; group = "chanserv/management"; }
|
||||
|
||||
/*
|
||||
* cs_list
|
||||
@@ -1066,10 +1067,8 @@ module
|
||||
listmax = 50
|
||||
}
|
||||
command { service = "ChanServ"; name = "LIST"; command = "chanserv/list"; }
|
||||
|
||||
command { service = "ChanServ"; name = "SET PRIVATE"; command = "chanserv/set/private"; }
|
||||
|
||||
|
||||
/*
|
||||
* cs_log
|
||||
*
|
||||
@@ -1155,7 +1154,6 @@ command { service = "ChanServ"; name = "DEHALFOP"; command = "chanserv/modes"; g
|
||||
command { service = "ChanServ"; name = "VOICE"; command = "chanserv/modes"; group = "chanserv/status"; set = "VOICE" }
|
||||
command { service = "ChanServ"; name = "DEVOICE"; command = "chanserv/modes"; group = "chanserv/status"; unset = "VOICE" }
|
||||
|
||||
|
||||
/*
|
||||
* cs_register
|
||||
*
|
||||
@@ -1178,9 +1176,6 @@ module
|
||||
{
|
||||
name = "cs_seen"
|
||||
|
||||
/* If set, uses the older 1.8 style seen, which is less resource intensive */
|
||||
simple = false
|
||||
|
||||
/* Sets the time to keep seen entries in the seen database. */
|
||||
purgetime = 90d
|
||||
}
|
||||
@@ -1228,7 +1223,7 @@ module
|
||||
* If set, persistent channels have their creation times lowered to their
|
||||
* original registration dates.
|
||||
*/
|
||||
persist_lower_ts = true
|
||||
persist_lower_ts = yes
|
||||
}
|
||||
command { service = "ChanServ"; name = "SET"; command = "chanserv/set"; group = "chanserv/management"; }
|
||||
command { service = "ChanServ"; name = "SET AUTOOP"; command = "chanserv/set/autoop"; }
|
||||
@@ -1269,7 +1264,15 @@ command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc
|
||||
*/
|
||||
module { name = "cs_status" }
|
||||
command { service = "ChanServ"; name = "STATUS"; command = "chanserv/status"; }
|
||||
command { service = "ChanServ"; name = "WHY"; command = "chanserv/status"; hide = true; }
|
||||
command { service = "ChanServ"; name = "WHY"; command = "chanserv/status"; hide = yes; }
|
||||
|
||||
/*
|
||||
* cs_statusupdate
|
||||
*
|
||||
* This module automatically updates users' status on channels when the
|
||||
* channel's access list is modified.
|
||||
*/
|
||||
module { name = "cs_statusupdate" }
|
||||
|
||||
/*
|
||||
* cs_suspend
|
||||
@@ -1330,7 +1333,7 @@ command { service = "ChanServ"; name = "SET KEEPTOPIC"; command = "chanserv/set/
|
||||
* Used for unbanning users from channels.
|
||||
*/
|
||||
module { name = "cs_unban" }
|
||||
command { service = "ChanServ"; name = "UNBAN"; command = "chanserv/unban"; }
|
||||
command { service = "ChanServ"; name = "UNBAN"; command = "chanserv/unban"; group = "chanserv/management"; }
|
||||
|
||||
/*
|
||||
* cs_updown
|
||||
@@ -1363,16 +1366,3 @@ command { service = "ChanServ"; name = "SOP"; command = "chanserv/xop"; group =
|
||||
command { service = "ChanServ"; name = "AOP"; command = "chanserv/xop"; group = "chanserv/access"; }
|
||||
command { service = "ChanServ"; name = "HOP"; command = "chanserv/xop"; group = "chanserv/access"; }
|
||||
command { service = "ChanServ"; name = "VOP"; command = "chanserv/xop"; group = "chanserv/access"; }
|
||||
|
||||
|
||||
/*
|
||||
* Extra ChanServ related modules.
|
||||
*/
|
||||
|
||||
/*
|
||||
* cs_statusupdate
|
||||
*
|
||||
* This module automatically updates users' status on channels when the
|
||||
* channel's access list is modified.
|
||||
*/
|
||||
module { name = "cs_statusupdate" }
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
/*
|
||||
* Example configuration file for Chanstats.
|
||||
*
|
||||
* You can enable Chanstats by default by adding CS_STATS to {chanserv}:defaults
|
||||
* and NS_STATS to {nickserv}:defaults.
|
||||
*
|
||||
* Make sure BotServ, ChanServ and NickServ are running.
|
||||
*/
|
||||
|
||||
@@ -23,12 +27,6 @@ module
|
||||
smileyshappy = ":) :-) ;) ;-) :D :-D :P :-P"
|
||||
smileyssad = ":( :-( ;( ;-("
|
||||
smileysother = ":/ :-/"
|
||||
|
||||
/*
|
||||
* Enable Chanstats for newly registered nicks / channels.
|
||||
*/
|
||||
ns_def_chanstats = yes
|
||||
cs_def_chanstats = yes
|
||||
}
|
||||
command { service = "ChanServ"; name = "SET CHANSTATS"; command = "chanserv/set/chanstats"; }
|
||||
command { service = "NickServ"; name = "SET CHANSTATS"; command = "nickserv/set/chanstats"; }
|
||||
|
||||
@@ -26,7 +26,7 @@ service
|
||||
/*
|
||||
* The realname of the Global client.
|
||||
*/
|
||||
gecos = "Global Noticer"
|
||||
real = "Global Noticer"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
@@ -93,7 +93,7 @@ module
|
||||
#globaloncycleup = "Services are now back online - have a nice day"
|
||||
|
||||
/*
|
||||
* If set, Anope will hide the IRC Operator's nick in a global
|
||||
* If set, Anope will hide the Services Operator's nick in a global
|
||||
* message/notice.
|
||||
*
|
||||
* This directive is optional.
|
||||
|
||||
+33
-14
@@ -26,7 +26,7 @@ service
|
||||
/*
|
||||
* The realname of the HostServ client.
|
||||
*/
|
||||
gecos = "vHost Service"
|
||||
real = "Hostname Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
@@ -106,7 +106,7 @@ command { service = "HostServ"; name = "HELP"; command = "generic/help"; }
|
||||
*
|
||||
* Provides the commands hostserv/del and hostserv/delall.
|
||||
*
|
||||
* Used for removing users' vHosts.
|
||||
* Used for removing users' vhosts.
|
||||
*/
|
||||
module { name = "hs_del" }
|
||||
command { service = "HostServ"; name = "DEL"; command = "hostserv/del"; permission = "hostserv/del"; }
|
||||
@@ -117,21 +117,21 @@ command { service = "HostServ"; name = "DELALL"; command = "hostserv/delall"; pe
|
||||
*
|
||||
* Provides the command hostserv/group.
|
||||
*
|
||||
* Used for grouping one vHost to many nicks.
|
||||
* Used for syncing one vhost to many nicks.
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "hs_group"
|
||||
|
||||
/*
|
||||
* Upon nickserv/group, this option syncs the nick's main vHost to the grouped nick.
|
||||
* Upon nickserv/group, this option syncs the nick's main vhost to the grouped nick.
|
||||
*/
|
||||
syncongroup = true
|
||||
syncongroup = yes
|
||||
|
||||
/*
|
||||
* This makes vhosts act as if they are per account.
|
||||
*/
|
||||
synconset = true
|
||||
synconset = yes
|
||||
}
|
||||
command { service = "HostServ"; name = "GROUP"; command = "hostserv/group"; }
|
||||
|
||||
@@ -140,7 +140,7 @@ command { service = "HostServ"; name = "GROUP"; command = "hostserv/group"; }
|
||||
*
|
||||
* Provides the command hostserv/list.
|
||||
*
|
||||
* Used for listing actively set vHosts.
|
||||
* Used for listing actively set vhosts.
|
||||
*/
|
||||
module { name = "hs_list" }
|
||||
command { service = "HostServ"; name = "LIST"; command = "hostserv/list"; permission = "hostserv/list"; }
|
||||
@@ -150,7 +150,7 @@ command { service = "HostServ"; name = "LIST"; command = "hostserv/list"; permis
|
||||
*
|
||||
* Provides the command hostserv/off.
|
||||
*
|
||||
* Used for turning off your vHost.
|
||||
* Used for turning off your vhost.
|
||||
*/
|
||||
module { name = "hs_off" }
|
||||
command { service = "HostServ"; name = "OFF"; command = "hostserv/off"; }
|
||||
@@ -160,7 +160,7 @@ command { service = "HostServ"; name = "OFF"; command = "hostserv/off"; }
|
||||
*
|
||||
* Provides the command hostserv/on.
|
||||
*
|
||||
* Used for turning on your vHost.
|
||||
* Used for turning on your vhost.
|
||||
*/
|
||||
module { name = "hs_on" }
|
||||
command { service = "HostServ"; name = "ON"; command = "hostserv/on"; }
|
||||
@@ -168,36 +168,55 @@ command { service = "HostServ"; name = "ON"; command = "hostserv/on"; }
|
||||
/*
|
||||
* hs_request
|
||||
*
|
||||
* Provides the commands hostserv/request, hostserv/activate, hostserv/reject, and hostserv/waiting.
|
||||
* Provides the commands:
|
||||
* hostserv/request - Requests a vhost.
|
||||
* hostserv/activate - Approves a requested vhost.
|
||||
* hostserv/reject - Rejects a requested vhost.
|
||||
* hostserv/waiting - Lists pending vhost requests.
|
||||
* hostserv/validate - Allows self-service approval of vhosts using DNS
|
||||
* validation (requires the dns module).
|
||||
*
|
||||
* Used to manage vHosts requested by users.
|
||||
* Used to manage vhosts requested by users.
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "hs_request"
|
||||
|
||||
/*
|
||||
* If set, Anope will send a memo to the user requesting a vHost when it's been
|
||||
* If set, Anope will send a memo to the user requesting a vhost when it's been
|
||||
* approved or rejected.
|
||||
*/
|
||||
#memouser = yes
|
||||
|
||||
/*
|
||||
* If set, Anope will send a memo to all services staff when a new vHost is requested.
|
||||
* If set, Anope will send a memo to all services staff when a new vhost is requested.
|
||||
*/
|
||||
#memooper = yes
|
||||
|
||||
/*
|
||||
* If DNS validation is enabled, how long should users have to wait between
|
||||
* attempts at DNS validation. Defaults to 5 minutes.
|
||||
*/
|
||||
#validationcooldown = 5m
|
||||
|
||||
/*
|
||||
* If DNS validation is enabled, the TXT record to look for when determining
|
||||
* if the requester controls the domain. Defaults to anope-dns-validation.
|
||||
*/
|
||||
#validationrecord = "anope-dns-validation"
|
||||
}
|
||||
command { service = "HostServ"; name = "REQUEST"; command = "hostserv/request"; }
|
||||
command { service = "HostServ"; name = "ACTIVATE"; command = "hostserv/activate"; permission = "hostserv/set"; }
|
||||
command { service = "HostServ"; name = "REJECT"; command = "hostserv/reject"; permission = "hostserv/set"; }
|
||||
command { service = "HostServ"; name = "WAITING"; command = "hostserv/waiting"; permission = "hostserv/set"; }
|
||||
#command { service = "HostServ"; name = "VALIDATE"; command = "hostserv/validate"; }
|
||||
|
||||
/*
|
||||
* hs_set
|
||||
*
|
||||
* Provides the commands hostserv/set and hostserv/setall.
|
||||
*
|
||||
* Used for setting users' vHosts.
|
||||
* Used for setting users' vhosts.
|
||||
*/
|
||||
module { name = "hs_set" }
|
||||
command { service = "HostServ"; name = "SET"; command = "hostserv/set"; permission = "hostserv/set"; }
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Example configuration file for the irc2sql gateway
|
||||
*
|
||||
*/
|
||||
|
||||
service
|
||||
{
|
||||
/*
|
||||
* The name of the StatServ client.
|
||||
*/
|
||||
nick = "StatServ"
|
||||
|
||||
/*
|
||||
* The username of the StatServ client.
|
||||
*/
|
||||
user = "StatServ"
|
||||
|
||||
/*
|
||||
* The hostname of the StatServ client.
|
||||
*/
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the StatServ client.
|
||||
*/
|
||||
gecos = "Statistical Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
* Do not modify this unless you know what you are doing.
|
||||
*
|
||||
* These modes are very IRCd specific. If left commented, sane defaults
|
||||
* are used based on what protocol module you have loaded.
|
||||
*
|
||||
* Note that setting this option incorrectly could potentially BREAK some, if
|
||||
* not all, usefulness of the client. We will not support you if this client is
|
||||
* unable to do certain things if this option is enabled.
|
||||
*/
|
||||
#modes = "+o"
|
||||
|
||||
/*
|
||||
* An optional comma separated list of channels this service should join. Outside
|
||||
* of log channels this is not very useful, as the service will just idle in the
|
||||
* specified channels, and will not accept any types of commands.
|
||||
*
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#stats,#mychan"
|
||||
}
|
||||
|
||||
module
|
||||
{
|
||||
name = "irc2sql"
|
||||
|
||||
/*
|
||||
* The name of the client that should send the CTCP VERSION requests.
|
||||
* It must already exist or must be defined in the following service block.
|
||||
*/
|
||||
client = "StatServ"
|
||||
|
||||
/*
|
||||
* The name of the SQL engine to use.
|
||||
* This must be MySQL and must match the name in the mysql{} block
|
||||
*/
|
||||
engine = "mysql/main"
|
||||
|
||||
/*
|
||||
* An optional prefix to prepended to the name of each created table.
|
||||
* Do not use the same prefix for other programs.
|
||||
*/
|
||||
prefix = "anope_"
|
||||
|
||||
/*
|
||||
* GeoIP - Automatically adds users geoip location to the user table.
|
||||
* Tables are created by irc2sql, you have to run the
|
||||
* geoipupdate script after you started Anope to download
|
||||
* and import the GeoIP database.
|
||||
*
|
||||
* The geoip database can be the smaller "country" database or the
|
||||
* larger "city" database. Comment to disable geoip lookup.
|
||||
*/
|
||||
geoip_database = "country"
|
||||
|
||||
/*
|
||||
* Get the CTCP version from users
|
||||
* The users connecting to the network will receive a CTCP VERSION
|
||||
* request from the above configured stats client
|
||||
*/
|
||||
ctcpuser = "yes"
|
||||
|
||||
/*
|
||||
* Send out CTCP VERSION requests to users during burst.
|
||||
* Disable this if you restart Anope often and don't want to
|
||||
* annoy your users.
|
||||
*/
|
||||
ctcpeob = "yes"
|
||||
}
|
||||
@@ -26,7 +26,7 @@ service
|
||||
/*
|
||||
* The realname of the MemoServ client.
|
||||
*/
|
||||
gecos = "Memo Service"
|
||||
real = "Memo Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
@@ -89,8 +89,7 @@ module
|
||||
/*
|
||||
* The delay between consecutive uses of the MemoServ SEND command. This can help prevent spam
|
||||
* as well as denial-of-service attacks from sending large numbers of memos and filling up disk
|
||||
* space (and memory). The default 3-second wait means a maximum average of 150 bytes of memo
|
||||
* per second per user under the current IRC protocol.
|
||||
* space (and memory).
|
||||
*
|
||||
* This directive is optional, but recommended.
|
||||
*/
|
||||
@@ -197,8 +196,6 @@ command { service = "MemoServ"; name = "READ"; command = "memoserv/read"; }
|
||||
* Provides the command memoserv/rsend.
|
||||
*
|
||||
* Used to send a memo requiring a receipt be sent back once it is read.
|
||||
*
|
||||
* Requires configuring memoserv:memoreceipt.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
@@ -209,7 +206,7 @@ command { service = "MemoServ"; name = "READ"; command = "memoserv/read"; }
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
operonly = false
|
||||
operonly = no
|
||||
}
|
||||
#command { service = "MemoServ"; name = "RSEND"; command = "memoserv/rsend"; }
|
||||
|
||||
|
||||
+115
-34
@@ -41,7 +41,6 @@ module { name = "help" }
|
||||
*/
|
||||
timeout = 5
|
||||
|
||||
|
||||
/* Only edit below if you are expecting to use os_dns or otherwise answer DNS queries. */
|
||||
|
||||
/*
|
||||
@@ -54,7 +53,6 @@ module { name = "help" }
|
||||
ip = "0.0.0.0"
|
||||
port = 53
|
||||
|
||||
|
||||
/*
|
||||
* SOA record information.
|
||||
*/
|
||||
@@ -65,7 +63,7 @@ module { name = "help" }
|
||||
/* This should be the names of the public facing nameservers serving the records. */
|
||||
nameservers = "ns1.example.com ns2.example.com"
|
||||
|
||||
/* The time slave servers are allowed to cache. This should be reasonably low
|
||||
/* The time secondary servers are allowed to cache for. This should be reasonably low
|
||||
* if you want your records to be updated without much delay.
|
||||
*/
|
||||
refresh = 3600
|
||||
@@ -233,7 +231,7 @@ module { name = "help" }
|
||||
}
|
||||
|
||||
/*
|
||||
* ldap [EXTRA]
|
||||
* [EXTRA] ldap
|
||||
*
|
||||
* This module allows other modules to use LDAP. By itself, this module does nothing useful.
|
||||
*/
|
||||
@@ -304,13 +302,13 @@ module { name = "help" }
|
||||
*
|
||||
* If not set, then registration is not blocked.
|
||||
*/
|
||||
#disable_register_reason = "To register on this network visit https://some.misconfigured.site/register"
|
||||
#disable_register_reason = "To register on this network visit https://some.misconfigured.site.example/register"
|
||||
|
||||
/*
|
||||
* If set, the reason to give the users who try to "/msg NickServ SET EMAIL".
|
||||
* If not set, then email changing is not blocked.
|
||||
*/
|
||||
#disable_email_reason = "To change your email address visit https://some.misconfigured.site"
|
||||
#disable_email_reason = "To change your email address visit https://some.misconfigured.site.example"
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -355,7 +353,7 @@ module { name = "help" }
|
||||
}
|
||||
|
||||
/*
|
||||
* mysql [EXTRA]
|
||||
* [EXTRA] mysql
|
||||
*
|
||||
* This module allows other modules to use MySQL.
|
||||
*/
|
||||
@@ -402,7 +400,7 @@ module { name = "help" }
|
||||
}
|
||||
|
||||
/*
|
||||
* regex_pcre2 [EXTRA]
|
||||
* [EXTRA] regex_pcre2
|
||||
*
|
||||
* Provides the regex engine regex/pcre, which uses version 2 of the Perl Compatible Regular
|
||||
* Expressions library.
|
||||
@@ -410,7 +408,7 @@ module { name = "help" }
|
||||
#module { name = "regex_pcre2" }
|
||||
|
||||
/*
|
||||
* regex_posix [EXTRA]
|
||||
* [EXTRA] regex_posix
|
||||
*
|
||||
* Provides the regex engine regex/posix, which uses the POSIX compliant regular expressions.
|
||||
*/
|
||||
@@ -440,7 +438,7 @@ module
|
||||
}
|
||||
|
||||
/*
|
||||
* regex_tre [EXTRA]
|
||||
* [EXTRA] regex_tre
|
||||
*
|
||||
* Provides the regex engine regex/tre, which uses the TRE regex library.
|
||||
*/
|
||||
@@ -457,7 +455,7 @@ module
|
||||
service = "ChanServ"; name = "CLEAR"; command = "rewrite"
|
||||
|
||||
/* Enable rewrite. */
|
||||
rewrite = true
|
||||
rewrite = yes
|
||||
|
||||
/* Source message to match. A $ can be used to match anything. */
|
||||
rewrite_source = "CLEAR $ USERS"
|
||||
@@ -559,7 +557,7 @@ module
|
||||
}
|
||||
|
||||
/*
|
||||
* ssl_gnutls [EXTRA]
|
||||
* [EXTRA] ssl_gnutls
|
||||
*
|
||||
* This module provides SSL services to Anope using GnuTLS, for example to
|
||||
* connect to the uplink server(s) via SSL.
|
||||
@@ -598,7 +596,7 @@ module
|
||||
}
|
||||
|
||||
/*
|
||||
* ssl_openssl [EXTRA]
|
||||
* [EXTRA] ssl_openssl
|
||||
*
|
||||
* This module provides SSL services to Anope using OpenSSL, for example to
|
||||
* connect to the uplink server(s) via SSL.
|
||||
@@ -691,20 +689,20 @@ module
|
||||
* If set, the reason to give the users who try to "/msg NickServ REGISTER".
|
||||
* If not set, then registration is not blocked.
|
||||
*/
|
||||
#disable_reason = "To register on this network visit https://some.misconfigured.site/register"
|
||||
#disable_reason = "To register on this network visit https://some.misconfigured.site.example/register"
|
||||
|
||||
/*
|
||||
* If set, the reason to give the users who try to "/msg NickServ SET EMAIL".
|
||||
* If not set, then email changing is not blocked.
|
||||
*/
|
||||
#disable_email_reason = "To change your email address visit https://some.misconfigured.site"
|
||||
#disable_email_reason = "To change your email address visit https://some.misconfigured.site.example"
|
||||
}
|
||||
|
||||
/*
|
||||
* sql_log
|
||||
*
|
||||
* This module adds an additional target option to log{} blocks
|
||||
* that allows logging Service's logs to SQL. To log to SQL, add
|
||||
* that allows logging Services' logs to SQL. To log to SQL, add
|
||||
* the SQL service name to log:targets prefixed by sql_log:. For
|
||||
* example:
|
||||
*
|
||||
@@ -723,8 +721,8 @@ module
|
||||
/*
|
||||
* sql_oper
|
||||
*
|
||||
* This module allows granting users services operator privileges and possibly IRC Operator
|
||||
* privileges based on an external SQL database using a custom query.
|
||||
* This module allows granting users Services Operator privileges based on an
|
||||
* external SQL database using a custom query.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
@@ -747,7 +745,7 @@ module
|
||||
}
|
||||
|
||||
/*
|
||||
* sqlite [EXTRA]
|
||||
* [EXTRA] sqlite
|
||||
*
|
||||
* This module allows other modules to use SQLite.
|
||||
*/
|
||||
@@ -795,8 +793,14 @@ module
|
||||
/*
|
||||
* jsonrpc
|
||||
*
|
||||
* Allows remote applications (websites) to execute queries in real time to retrieve data from Anope.
|
||||
* By itself this module does nothing, but allows other modules (rpc_main) to receive and send JSON-RPC queries.
|
||||
* Allows remote applications to execute methods within Anope using the JSON-RPC
|
||||
* protocol. See https://www.jsonrpc.org/specification for more information.
|
||||
*
|
||||
* By itself this module does nothing. You should load a RPC method module like
|
||||
* rpc_data which actually provides RPC methods.
|
||||
*
|
||||
* See docs/RPC/jsonrpc.js for an example JavaScript JSON-RPC client.
|
||||
* See docs/RPC/jsonrpc.rb for an example Ruby JSON-RPC client.
|
||||
*
|
||||
* IMPORTANT: this can not be loaded at the same time as the xmlrpc module.
|
||||
*/
|
||||
@@ -804,15 +808,54 @@ module
|
||||
{
|
||||
name = "jsonrpc"
|
||||
|
||||
/*
|
||||
* The maximum number of bits an integer can be have in its native type.
|
||||
*
|
||||
* By default Anope will emit integers as their native JSON type. If you are
|
||||
* using JavaScript (which has 53 bit integers) or another language with
|
||||
* native integer types smaller than 64 bits you may need to limit the size
|
||||
* of integers emitted by Anope.
|
||||
*
|
||||
* If this is enabled a string will be used for values outside of the range
|
||||
* supported by the native data type.
|
||||
*/
|
||||
#integer_bits = 53
|
||||
|
||||
/* Web service to use. Requires httpd. */
|
||||
server = "httpd/main"
|
||||
|
||||
/*
|
||||
* You can also specify one or more authorization tokens to protect access
|
||||
* to the JSON-RPC interface. These tokens should be sent using the Bearer
|
||||
* authorization header as defined in RFC 6750.
|
||||
*/
|
||||
#token
|
||||
{
|
||||
/* The token used for authentication. */
|
||||
token = "BmcxTaiYjoBtayfnxCFq"
|
||||
|
||||
/*
|
||||
* The algorithm which the above token is hashed with. If this is not
|
||||
* set then services will assume the above password is not hashed.
|
||||
*
|
||||
* You will need to have the appropriate encryption module (e.g.
|
||||
* enc_bcrypt) loaded in order for this to work.
|
||||
*/
|
||||
#token_hash = "bcrypt"
|
||||
|
||||
/** A list of glob patterns for methods the token can execute. */
|
||||
methods = "~anope.message* anope.*"
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* [EXTRA] xmlrpc
|
||||
*
|
||||
* Allows remote applications (websites) to execute queries in real time to retrieve data from Anope.
|
||||
* By itself this module does nothing, but allows other modules (rpc_main) to receive and send XMLRPC queries.
|
||||
* Allows remote applications to execute methods within Anope using the XML-RPC
|
||||
* protocol. See https://xmlrpc.com/spec.md for more information.
|
||||
*
|
||||
* By itself this module does nothing. You should load a RPC method module like
|
||||
* rpc_data which actually provides RPC methods.
|
||||
*
|
||||
* IMPORTANT: this can not be loaded at the same time as the jsonrpc module.
|
||||
*/
|
||||
@@ -820,9 +863,6 @@ module
|
||||
{
|
||||
name = "xmlrpc"
|
||||
|
||||
/* Web service to use. Requires httpd. */
|
||||
server = "httpd/main"
|
||||
|
||||
/*
|
||||
* Whether to enable the use of XML-RPC extensions.
|
||||
*
|
||||
@@ -836,6 +876,55 @@ module
|
||||
*/
|
||||
#enable_i8 = no
|
||||
#enable_nil = no
|
||||
|
||||
/* Web service to use. Requires httpd. */
|
||||
server = "httpd/main"
|
||||
|
||||
/*
|
||||
* You can also specify one or more authorization tokens to protect access
|
||||
* to the XML-RPC interface. These tokens should be sent using the Bearer
|
||||
* authorization header as defined in RFC 6750.
|
||||
*/
|
||||
#token
|
||||
{
|
||||
/* The token used for authentication. */
|
||||
token = "BmcxTaiYjoBtayfnxCFq"
|
||||
|
||||
/*
|
||||
* The algorithm which the above token is hashed with. If this is not
|
||||
* set then services will assume the above password is not hashed.
|
||||
*
|
||||
* You will need to have the appropriate encryption module (e.g.
|
||||
* enc_bcrypt) loaded in order for this to work.
|
||||
*/
|
||||
#token_hash = "bcrypt"
|
||||
|
||||
/** A list of glob patterns for methods the token can execute. */
|
||||
methods = "~anope.message* anope.*"
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rpc_user
|
||||
*
|
||||
* Adds support for the following RPC methods:
|
||||
*
|
||||
* anope.checkCredentials anope.identify
|
||||
* anope.listCommands anope.command
|
||||
*
|
||||
* Requires either the jsonrpc or xmlrpc module.
|
||||
*
|
||||
* See docs/RPC/rpc_user.md for API documentation.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "rpc_user"
|
||||
|
||||
/*
|
||||
* Some commands can only be executed by a real IRC user. You can work around
|
||||
* this executing them as an IRC user logged into the account if one exists.
|
||||
*/
|
||||
pretenduser = no
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -855,14 +944,6 @@ module
|
||||
*/
|
||||
#module { name = "rpc_data" }
|
||||
|
||||
/*
|
||||
* rpc_main
|
||||
*
|
||||
* Adds the main RPC core functions.
|
||||
* Requires xmlrpc.
|
||||
*/
|
||||
#module { name = "rpc_main" }
|
||||
|
||||
/*
|
||||
* rpc_message
|
||||
*
|
||||
|
||||
+166
-78
@@ -26,7 +26,7 @@ service
|
||||
/*
|
||||
* The realname of the NickServ client.
|
||||
*/
|
||||
gecos = "Nickname Registration Service"
|
||||
real = "Nickname Registration Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
@@ -118,6 +118,7 @@ module
|
||||
* - msg: Messages will be sent as PRIVMSGs instead of NOTICEs
|
||||
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
|
||||
* - protect: Protects the registered nickname from use by unidentified users.
|
||||
* - ns_stats: Enable Chanstats for newly registered nicks
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to memo_signon, and
|
||||
* memo_receive. If you really want no defaults, use "none" by itself as the option.
|
||||
@@ -164,7 +165,7 @@ module
|
||||
* If set, Anope will not show netsplits in the last quit message field
|
||||
* of NickServ's INFO command.
|
||||
*/
|
||||
hidenetsplitquit = no
|
||||
hidenetsplitquit = yes
|
||||
|
||||
/*
|
||||
* The default period to force users to stop using a protected nickname after.
|
||||
@@ -202,11 +203,13 @@ module
|
||||
#restrictopernicks = yes
|
||||
|
||||
/*
|
||||
* The username, and possibly hostname, used for fake users created when Anope needs to
|
||||
* hold a nickname.
|
||||
* The username, hostname, and real name used for pseudoclients created when
|
||||
* Anope needs to hold a nickname. This is only used if your IRCd does not
|
||||
* support SVSHOLDs.
|
||||
*/
|
||||
enforceruser = "enforcer"
|
||||
enforcerhost = "${services.host}"
|
||||
enforcerreal = "Services Enforcer"
|
||||
|
||||
/*
|
||||
* The length of time Anope should hold nicknames for.
|
||||
@@ -248,8 +251,8 @@ module
|
||||
maxpasslen = 50
|
||||
|
||||
/*
|
||||
* Whether all of the secondary nicks of a nick group have to expire or be
|
||||
dropped before the display nick can expire or be dropped.
|
||||
* Whether all of the secondary nicks of an account have to expire or be
|
||||
* dropped before the display nick can expire or be dropped.
|
||||
*/
|
||||
preservedisplay = no
|
||||
}
|
||||
@@ -306,7 +309,7 @@ command { service = "NickServ"; name = "AJOIN"; command = "nickserv/ajoin"; }
|
||||
*/
|
||||
module { name = "ns_alist" }
|
||||
command { service = "NickServ"; name = "ALIST"; command = "nickserv/alist"; }
|
||||
command { service = "NickServ"; name = "ACCESS"; command = "nickserv/alist"; hide = true; }
|
||||
command { service = "NickServ"; name = "ACCESS"; command = "nickserv/alist"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_cert
|
||||
@@ -333,6 +336,16 @@ module
|
||||
}
|
||||
command { service = "NickServ"; name = "CERT"; command = "nickserv/cert"; }
|
||||
|
||||
/*
|
||||
* ns_confirm
|
||||
*
|
||||
* Provides the command nickserv/confirm.
|
||||
*
|
||||
* Used for confirming previous account actions.
|
||||
*/
|
||||
module { name = "ns_confirm" }
|
||||
command { service = "NickServ"; name = "CONFIRM"; command = "nickserv/confirm"; }
|
||||
|
||||
/*
|
||||
* ns_drop
|
||||
*
|
||||
@@ -344,21 +357,56 @@ module { name = "ns_drop" }
|
||||
command { service = "NickServ"; name = "DROP"; command = "nickserv/drop"; }
|
||||
|
||||
/*
|
||||
* ns_getemail
|
||||
* ns_email
|
||||
*
|
||||
* Provides the command nickserv/getemail.
|
||||
* Provides various functionality relating to email addresses. This includes the
|
||||
* following commands:
|
||||
*
|
||||
* Used for getting registered accounts by searching for emails.
|
||||
* - nickserv/confirm/email: Used for confirming email changes.
|
||||
* - nickserv/getemail: Used for getting accounts by searching for emails.
|
||||
* - nickserv/set/email, nickserv/saset/email: Used for setting an account's
|
||||
* emailvaddress.
|
||||
*/
|
||||
module { name = "ns_getemail" }
|
||||
module
|
||||
{
|
||||
name = "ns_email"
|
||||
|
||||
/*
|
||||
* The amount of time a user has after requesting a change of email address
|
||||
* before it expires. Defaults to 1 day.
|
||||
*/
|
||||
#changeexpire = 1d
|
||||
|
||||
/*
|
||||
* The limit to how many registered accounts can use the same email address.
|
||||
* If set to 0 or left commented there will be no limit enforced when
|
||||
* registering new accounts or using /msg NickServ SET EMAIL.
|
||||
*/
|
||||
#maxemails = 1
|
||||
|
||||
/*
|
||||
* Whether to attempt to remove aliases when counting email addresses. This
|
||||
* means removing dots (.) and anything after a plus (+) in the user part of
|
||||
* the address, e.g. foo.bar+baz@example.com -> foobar@example.com.
|
||||
*/
|
||||
#remove_aliases = yes
|
||||
}
|
||||
command { service = "NickServ"; name = "CONFIRM EMAIL"; command = "nickserv/confirm/email"; }
|
||||
command { service = "NickServ"; name = "GETEMAIL"; command = "nickserv/getemail"; permission = "nickserv/getemail"; group = "nickserv/admin"; }
|
||||
command { service = "NickServ"; name = "SET EMAIL"; command = "nickserv/set/email"; }
|
||||
command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/email"; permission = "nickserv/saset/email"; }
|
||||
|
||||
/*
|
||||
* ns_group
|
||||
*
|
||||
* Provides the commands nickserv/group, nickserv/glist, and nickserv/ungroup.
|
||||
* Provides the commands:
|
||||
* nickserv/group
|
||||
* nickserv/ungroup
|
||||
* nickserv/glist
|
||||
* nickserv/saset/display
|
||||
* nickserv/set/display
|
||||
*
|
||||
* Used for controlling nick groups.
|
||||
* Used for controlling grouped nicknames.
|
||||
*/
|
||||
module
|
||||
{
|
||||
@@ -383,6 +431,12 @@ module
|
||||
command { service = "NickServ"; name = "GLIST"; command = "nickserv/glist"; }
|
||||
command { service = "NickServ"; name = "GROUP"; command = "nickserv/group"; }
|
||||
command { service = "NickServ"; name = "UNGROUP"; command = "nickserv/ungroup"; }
|
||||
command { service = "NickServ"; name = "SET DISPLAY"; command = "nickserv/set/display"; }
|
||||
command { service = "NickServ"; name = "SASET DISPLAY"; command = "nickserv/saset/display"; permission = "nickserv/saset/display"; }
|
||||
|
||||
# For compatibility with Atheme.
|
||||
command { service = "NickServ"; name = "SET ACCOUNTNAME"; command = "nickserv/set/display"; hide = yes; }
|
||||
command { service = "NickServ"; name = "SASET ACCOUNTNAME"; command = "nickserv/saset/display"; permission = "nickserv/saset/display"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_identify
|
||||
@@ -400,7 +454,7 @@ module
|
||||
*/
|
||||
maxlogins = 10
|
||||
}
|
||||
command { service = "NickServ"; name = "ID"; command = "nickserv/identify"; hide = true; }
|
||||
command { service = "NickServ"; name = "ID"; command = "nickserv/identify"; hide = yes; }
|
||||
command { service = "NickServ"; name = "IDENTIFY"; command = "nickserv/identify"; }
|
||||
|
||||
/*
|
||||
@@ -417,7 +471,6 @@ command { service = "NickServ"; name = "INFO"; command = "nickserv/info"; }
|
||||
command { service = "NickServ"; name = "SET HIDE"; command = "nickserv/set/hide"; }
|
||||
command { service = "NickServ"; name = "SASET HIDE"; command = "nickserv/saset/hide"; permission = "nickserv/saset/hide"; }
|
||||
|
||||
|
||||
/*
|
||||
* ns_list
|
||||
*
|
||||
@@ -436,11 +489,9 @@ module
|
||||
listmax = 50
|
||||
}
|
||||
command { service = "NickServ"; name = "LIST"; command = "nickserv/list"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET PRIVATE"; command = "nickserv/set/private"; }
|
||||
command { service = "NickServ"; name = "SASET PRIVATE"; command = "nickserv/saset/private"; permission = "nickserv/saset/private"; }
|
||||
|
||||
|
||||
/*
|
||||
* ns_logout
|
||||
*
|
||||
@@ -473,13 +524,13 @@ module
|
||||
command { service = "NickServ"; name = "RECOVER"; command = "nickserv/recover"; }
|
||||
|
||||
# For compatibility with Anope 1.8 and Atheme.
|
||||
command { service = "NickServ"; name = "GHOST"; command = "nickserv/recover"; hide = true; }
|
||||
command { service = "NickServ"; name = "RELEASE"; command = "nickserv/recover"; hide = true; }
|
||||
command { service = "NickServ"; name = "GHOST"; command = "nickserv/recover"; hide = yes; }
|
||||
command { service = "NickServ"; name = "RELEASE"; command = "nickserv/recover"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_register
|
||||
*
|
||||
* Provides the commands nickserv/confirm, nickserv/register, and nickserv/resend.
|
||||
* Provides the commands nickserv/confirm/register, nickserv/register, and nickserv/resend.
|
||||
*
|
||||
* Used for registering accounts.
|
||||
*/
|
||||
@@ -488,11 +539,15 @@ module
|
||||
name = "ns_register"
|
||||
|
||||
/*
|
||||
* Registration confirmation setting. Set to "none" for no registration confirmation,
|
||||
* "mail" for email confirmation, and "admin" to have services operators manually confirm
|
||||
* every registration. Set to "disable" to completely disable all registrations.
|
||||
* The method for confirming account registrations. Possible values are:
|
||||
*
|
||||
* "admin" to require confirmation by a Services Operator.
|
||||
* "code" to require confirmation with a code provided via IRC.
|
||||
* "disable" to disable account registration.
|
||||
* "mail" to require confirmation with a code provided via email.
|
||||
* "none" to automatically confirm (this is the default).
|
||||
*/
|
||||
registration = "none"
|
||||
registration = "code"
|
||||
|
||||
/*
|
||||
* The minimum length of time between consecutive uses of NickServ's RESEND command.
|
||||
@@ -507,7 +562,7 @@ module
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
nickregdelay = 15s
|
||||
#nickregdelay = 1m
|
||||
|
||||
/*
|
||||
* The length of time a user using an unconfirmed account has
|
||||
@@ -515,20 +570,33 @@ module
|
||||
*/
|
||||
#unconfirmedexpire = 1d
|
||||
}
|
||||
command { service = "NickServ"; name = "CONFIRM"; command = "nickserv/confirm"; }
|
||||
command { service = "NickServ"; name = "CONFIRM REGISTER"; command = "nickserv/confirm/register"; }
|
||||
command { service = "NickServ"; name = "REGISTER"; command = "nickserv/register"; }
|
||||
command { service = "NickServ"; name = "RESEND"; command = "nickserv/resend"; }
|
||||
|
||||
/*
|
||||
* ns_resetpass
|
||||
*
|
||||
* Provides the command nickserv/resetpass.
|
||||
* Provides the command nickserv/confirm/resetpass and nickserv/resetpass.
|
||||
*
|
||||
* Used for resetting passwords by emailing users a temporary one.
|
||||
*/
|
||||
module { name = "ns_resetpass" }
|
||||
module
|
||||
{
|
||||
name = "ns_resetpass"
|
||||
|
||||
/*
|
||||
* The amount of time a user has after requesting a password reset before it
|
||||
* expires. Defaults to 1 day.
|
||||
*/
|
||||
#resetexpire = 1d
|
||||
}
|
||||
command { service = "NickServ"; name = "CONFIRM RESETPASS"; command = "nickserv/confirm/resetpass"; }
|
||||
command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpass"; }
|
||||
|
||||
# For compatibility with Anope 2.0.
|
||||
command { service = "NickServ"; name = "GETPASS"; command = "nickserv/resetpass"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_sasl
|
||||
*
|
||||
@@ -548,18 +616,46 @@ module
|
||||
* The nick of the client which operates as the SASL agent.
|
||||
*/
|
||||
#agent = "NickServ"
|
||||
|
||||
/*
|
||||
* Sets the number of invalid SASL authentication attempts before services
|
||||
* removes a partially-connected user from the network. If not defined then
|
||||
* the value specified in options:badpasslimit will be used instead.
|
||||
*/
|
||||
#badpasslimit = 1
|
||||
|
||||
/*
|
||||
* Sets the time after which invalid SASL authentication attempts are
|
||||
* forgotten about. If a user does not fail to authenticate in this amount
|
||||
* of time, the incorrect password count will reset to zero. If not defined
|
||||
* then the value specified in options:badpasstimeout will be used instead.
|
||||
*/
|
||||
#badpasstimeout = 15m
|
||||
}
|
||||
|
||||
/*
|
||||
* ns_sasl_anonymous, ns_sasl_external, ns_sasl_plain
|
||||
*
|
||||
* Provides support for the following SASL mechanisms:
|
||||
*
|
||||
* ns_sasl_anonymous: Adds the ANONYMOUS mechanism which allows logging out of
|
||||
* an account. See RFC 4505 for more details.
|
||||
* ns_sasl_external: Adds the EXTERNAL mechanism which allows logging into an
|
||||
account using a TLS client certificate. See RFC 4422 for
|
||||
for more details.
|
||||
* ns_sasl_plain: Adds the PLAIN mechanism which allows logging in to an
|
||||
account using a plain text username and password. See RFC
|
||||
4422 for more details.
|
||||
*/
|
||||
module { name = "ns_sasl_anonymous" }
|
||||
module { name = "ns_sasl_external" }
|
||||
module { name = "ns_sasl_plain" }
|
||||
|
||||
/*
|
||||
* ns_set
|
||||
*
|
||||
* Provides the commands:
|
||||
* nickserv/set, nickserv/saset - Dummy help wrappers for the SET and SASET commands.
|
||||
* nickserv/set/autoop, nickserv/saset/autoop - Determines whether or not modes are automatically set users when joining a channel.
|
||||
* nickserv/set/display, nickserv/saset/display - Used for setting a users display name.
|
||||
* 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/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.
|
||||
*/
|
||||
@@ -568,21 +664,9 @@ module { name = "ns_set" }
|
||||
command { service = "NickServ"; name = "SET"; command = "nickserv/set"; }
|
||||
command { service = "NickServ"; name = "SASET"; command = "nickserv/saset"; permission = "nickserv/saset/"; group = "nickserv/admin"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET AUTOOP"; command = "nickserv/set/autoop"; }
|
||||
command { service = "NickServ"; name = "SASET AUTOOP"; command = "nickserv/saset/autoop"; permission = "nickserv/saset/autoop"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET DISPLAY"; command = "nickserv/set/display"; }
|
||||
command { service = "NickServ"; name = "SASET DISPLAY"; command = "nickserv/saset/display"; permission = "nickserv/saset/display"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET EMAIL"; command = "nickserv/set/email"; }
|
||||
command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/email"; permission = "nickserv/saset/email"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; }
|
||||
command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; permission = "nickserv/saset/password"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET NEVEROP"; command = "nickserv/set/neverop"; }
|
||||
command { service = "NickServ"; name = "SASET NEVEROP"; command = "nickserv/saset/neverop"; permission = "nickserv/saset/neverop"; }
|
||||
|
||||
command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; permission = "nickserv/saset/noexpire"; }
|
||||
|
||||
/*
|
||||
@@ -617,6 +701,17 @@ 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_layout
|
||||
*
|
||||
* Provides the command nickserv/set/layout and nickserv/saset/layout.
|
||||
*
|
||||
* Allows configuring the layout that services uses.
|
||||
*/
|
||||
module { name = "ns_set_layout" }
|
||||
command { service = "NickServ"; name = "SET LAYOUT"; command = "nickserv/set/layout"; }
|
||||
command { service = "NickServ"; name = "SASET LAYOUT"; command = "nickserv/saset/layout"; permission = "nickserv/saset/layout"; }
|
||||
|
||||
/*
|
||||
* ns_set_message
|
||||
*
|
||||
@@ -643,28 +738,44 @@ command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/sas
|
||||
module { name = "ns_set_misc" }
|
||||
command { service = "NickServ"; name = "SET URL"; command = "nickserv/set/misc"; misc_description = _("Associate a URL with your account"); }
|
||||
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 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"; }
|
||||
#command { service = "NickServ"; name = "SET LOCATION"; command = "nickserv/set/misc"; misc_description = _("Associate a location with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET LOCATION"; command = "nickserv/saset/misc"; misc_description = _("Associate a location with this account"); permission = "nickserv/saset/location"; group = "nickserv/admin"; }
|
||||
|
||||
/*
|
||||
* ns_set_op
|
||||
*
|
||||
* Provides the commands:
|
||||
* nickserv/set/autoop, nickserv/saset/autoop - Allows configuring whether status modes are automatically granted when joining a channel.
|
||||
* nickserv/set/neverop, nickserv/saset/neverop - Allows configuring whether a user can be added to access lists.
|
||||
*/
|
||||
module { name = "ns_set_op" }
|
||||
|
||||
command { service = "NickServ"; name = "SET AUTOOP"; command = "nickserv/set/autoop"; }
|
||||
command { service = "NickServ"; name = "SASET AUTOOP"; command = "nickserv/saset/autoop"; permission = "nickserv/saset/autoop"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET NEVEROP"; command = "nickserv/set/neverop"; }
|
||||
command { service = "NickServ"; name = "SASET NEVEROP"; command = "nickserv/saset/neverop"; permission = "nickserv/saset/neverop"; }
|
||||
|
||||
# For compatibility with DALnet Services.
|
||||
command { service = "NickServ"; name = "SET NOOP"; command = "nickserv/set/neverop"; hide = yes; }
|
||||
command { service = "NickServ"; name = "SASET NOOP"; command = "nickserv/saset/neverop"; permission = "nickserv/saset/neverop"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_set_protect
|
||||
*
|
||||
* Provides the commands nickserv/set/protect and kickserv/saset/protect.
|
||||
* Provides the commands nickserv/set/protect and nickserv/saset/protect.
|
||||
*
|
||||
* Used for configuring nickname protection.
|
||||
*/
|
||||
module { name = "ns_set_protect" }
|
||||
|
||||
command { service = "NickServ"; name = "SET PROTECT"; command = "nickserv/set/protect"; }
|
||||
command { service = "NickServ"; name = "SASET PROTECT"; command = "nickserv/saset/protect"; permission = "nickserv/saset/kill"; }
|
||||
command { service = "NickServ"; name = "SASET PROTECT"; command = "nickserv/saset/protect"; permission = "nickserv/saset/protect"; }
|
||||
|
||||
# For compatibility with Anope 2.0.
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/protect"; hide = true; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/protect"; permission = "nickserv/saset/protect"; hide = true; }
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/protect"; hide = yes; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/protect"; permission = "nickserv/saset/protect"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_suspend
|
||||
@@ -699,30 +810,7 @@ command { service = "NickServ"; name = "UNSUSPEND"; command = "nickserv/unsuspen
|
||||
*
|
||||
* Provides the command nickserv/update.
|
||||
*
|
||||
* Used to update your status on all channels, turn on your vHost, etc.
|
||||
* Used to update your status on all channels, turn on your vhost, etc.
|
||||
*/
|
||||
module { name = "ns_update" }
|
||||
command { service = "NickServ"; name = "UPDATE"; command = "nickserv/update"; }
|
||||
|
||||
|
||||
/*
|
||||
* Extra NickServ related modules.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ns_maxemail
|
||||
*
|
||||
* Limits how many times the same email address may be used in Anope
|
||||
* to register accounts.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "ns_maxemail"
|
||||
|
||||
/*
|
||||
* The limit to how many registered nicks can use the same email address. If set to 0 or left
|
||||
* commented, there will be no limit enforced when registering new accounts or using
|
||||
* /msg NickServ SET EMAIL.
|
||||
*/
|
||||
maxemails = 1
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ service
|
||||
/*
|
||||
* The realname of the OperServ client.
|
||||
*/
|
||||
gecos = "Operator Service"
|
||||
real = "Operator Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
@@ -111,7 +111,7 @@ module
|
||||
killonsqline = yes
|
||||
|
||||
/*
|
||||
* Adds the nickname of the IRC Operator issuing an AKILL to the kill reason.
|
||||
* Adds the nickname of the Services Operator issuing an AKILL to the kill reason.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
@@ -287,15 +287,15 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
|
||||
* To use this module you must set a nameserver record for services
|
||||
* so that DNS queries go to services.
|
||||
*
|
||||
* Alternatively, you may use a slave DNS server to hide service's IP,
|
||||
* Alternatively, you may use a secondary DNS server to hide services' IP,
|
||||
* provide query caching, and provide better fault tolerance.
|
||||
*
|
||||
* To do this using BIND, configure similar to:
|
||||
*
|
||||
* options { max-refresh-time 60; };
|
||||
* zone "irc.example.com" IN {
|
||||
* type slave;
|
||||
* masters { 127.0.0.1 port 5353; };
|
||||
* type secondary;
|
||||
* primaries { 127.0.0.1 port 5353; };
|
||||
* };
|
||||
*
|
||||
* Where 127.0.0.1:5353 is the IP and port services are listening on.
|
||||
|
||||
@@ -1,515 +0,0 @@
|
||||
/*
|
||||
* Example configuration file for Anope. After making the appropriate
|
||||
* changes to this file, place it in the Anope conf directory (as
|
||||
* specified in the "Config" script, default /home/username/anope/conf)
|
||||
* under the name "anope.conf".
|
||||
*
|
||||
* The format of this file is fairly simple: three types of comments are supported:
|
||||
* - All text after a '#' on a line is ignored, as in shell scripting
|
||||
* - All text after '//' on a line is ignored, as in C++
|
||||
* - A block of text like this one is ignored, as in C
|
||||
*
|
||||
* Outside of comments, there are three structures: blocks, keys, and values.
|
||||
*
|
||||
* A block is a named container, which contains a number of key to value pairs
|
||||
* - you may think of this as an array.
|
||||
*
|
||||
* A block is created like so:
|
||||
* foobar
|
||||
* {
|
||||
* moo = "cow"
|
||||
* foo = bar
|
||||
* }
|
||||
*
|
||||
* Note that nameless blocks are allowed and are often used with comments to allow
|
||||
* easily commenting an entire block, for example:
|
||||
* #foobar
|
||||
* {
|
||||
* moo = "cow"
|
||||
* foo = bar
|
||||
* }
|
||||
* is an entirely commented block.
|
||||
*
|
||||
* Keys are case insensitive. Values depend on what key - generally, information is
|
||||
* given in the key comment. The quoting of values (and most other syntax) is quite
|
||||
* flexible, however, please do not forget to quote your strings:
|
||||
*
|
||||
* "This is a parameter string with spaces in it"
|
||||
*
|
||||
* If you need to include a double quote inside a quoted string, precede it
|
||||
* by a backslash:
|
||||
*
|
||||
* "This string has \"double quotes\" in it"
|
||||
*
|
||||
* Time parameters can be specified either as an integer representing a
|
||||
* number of seconds (e.g. "3600" = 1 hour), or as an integer with a unit
|
||||
* specifier: "s" = seconds, "m" = minutes, "h" = hours, "d" = days.
|
||||
* Combinations (such as "1h30m") are not permitted. Examples (all of which
|
||||
* represent the same length of time, one day):
|
||||
*
|
||||
* "86400", "86400s", "1440m", "24h", "1d"
|
||||
*
|
||||
* In the documentation for each directive, one of the following will be
|
||||
* included to indicate whether an option is required:
|
||||
*
|
||||
* [REQUIRED]
|
||||
* Indicates a directive which must be given. Without it, Anope will
|
||||
* not start.
|
||||
*
|
||||
* [RECOMMENDED]
|
||||
* Indicates a directive which may be omitted, but omitting it may cause
|
||||
* undesirable side effects.
|
||||
*
|
||||
* [OPTIONAL]
|
||||
* Indicates a directive which is optional. If not given, the feature
|
||||
* will typically be disabled. If this is not the case, more
|
||||
* information will be given in the documentation.
|
||||
*
|
||||
* [DISCOURAGED]
|
||||
* Indicates a directive which may cause undesirable side effects if
|
||||
* specified.
|
||||
*
|
||||
* [DEPRECATED]
|
||||
* Indicates a directive which will disappear in a future version of
|
||||
* Anope, usually because its functionality has been either
|
||||
* superseded by that of other directives or incorporated into the main
|
||||
* program.
|
||||
*/
|
||||
|
||||
/*
|
||||
* [OPTIONAL] Defines
|
||||
*
|
||||
* You can use defines for repeated information, which can be used to easily change many
|
||||
* values in the configuration at once.
|
||||
*
|
||||
* To use a define called foo.bar you use ${foo.bar} in your config file. You can also use
|
||||
* environment variables by prefixing their name with "env." like ${env.USER}.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
*/
|
||||
define
|
||||
{
|
||||
name = "services.host"
|
||||
value = "stats.example.com"
|
||||
}
|
||||
|
||||
/*
|
||||
* [OPTIONAL] Additional Includes
|
||||
*
|
||||
* You can include additional configuration files here.
|
||||
* You may also include executable files, which will be executed and
|
||||
* the output from it will be included into your configuration.
|
||||
*/
|
||||
|
||||
#include
|
||||
{
|
||||
type = "file"
|
||||
name = "some.conf"
|
||||
}
|
||||
|
||||
#include
|
||||
{
|
||||
type = "executable"
|
||||
name = "/usr/bin/wget -q -O - https://some.misconfigured.network.com/stats.conf"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] IRCd Config
|
||||
*
|
||||
* This section is used to set up Anope to connect to your IRC network.
|
||||
* This section can be included multiple times, and Anope will attempt to
|
||||
* connect to each server until it finally connects.
|
||||
*
|
||||
* Each uplink IRCd should have a corresponding configuration to allow Anope
|
||||
* to link to it.
|
||||
*
|
||||
* An example configuration for InspIRCd that is compatible with the below uplink
|
||||
* and serverinfo configuration would look like:
|
||||
*
|
||||
* # This goes in inspircd.conf, *NOT* your Anope config!
|
||||
* <link name="stats.example.com"
|
||||
* ipaddr="127.0.0.1"
|
||||
* port="7000"
|
||||
* sendpass="mypassword"
|
||||
* recvpass="mypassword">
|
||||
* <uline server="stats.example.com" silent="yes">
|
||||
* <bind address="127.0.0.1" port="7000" type="servers">
|
||||
*
|
||||
* An example configuration for UnrealIRCd that is compatible with the below uplink
|
||||
* and serverinfo configuration would look like:
|
||||
*
|
||||
* // This goes in unrealircd.conf, *NOT* your Anope config!
|
||||
* listen {
|
||||
* ip 127.0.0.1;
|
||||
* port 7000;
|
||||
* options {
|
||||
* serversonly;
|
||||
* };
|
||||
* };
|
||||
* link stats.example.com {
|
||||
* incoming {
|
||||
* mask *@127.0.0.1;
|
||||
* };
|
||||
* password "mypassword";
|
||||
* class servers;
|
||||
* };
|
||||
* ulines { stats.example.com; };
|
||||
*/
|
||||
uplink
|
||||
{
|
||||
/*
|
||||
* The IP address, hostname, or UNIX socket path of the IRC server you wish
|
||||
* to connect Anope to.
|
||||
* Usually, you will want to connect over 127.0.0.1 (aka localhost).
|
||||
*
|
||||
* NOTE: On some shell providers, this will not be an option.
|
||||
*/
|
||||
host = "127.0.0.1"
|
||||
|
||||
/*
|
||||
* The protocol that Anope should use when connecting to the uplink. Can
|
||||
* be set to "ipv4" (the default), "ipv6", or "unix".
|
||||
*/
|
||||
protocol = "ipv4"
|
||||
|
||||
/*
|
||||
* Enable if Anope should connect using SSL.
|
||||
* You must have an SSL module loaded for this to work.
|
||||
*/
|
||||
ssl = no
|
||||
|
||||
/*
|
||||
* The port to connect to.
|
||||
* The IRCd *MUST* be configured to listen on this port, and to accept
|
||||
* server connections.
|
||||
*
|
||||
* Refer to your IRCd documentation for how this is to be done.
|
||||
*/
|
||||
port = 7000
|
||||
|
||||
/*
|
||||
* The password to send to the IRC server for authentication.
|
||||
* This must match the link block on your IRCd.
|
||||
*
|
||||
* Refer to your IRCd documentation for more information on link blocks.
|
||||
*/
|
||||
password = "mypassword"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Server Information
|
||||
*
|
||||
* This section contains information about the services server.
|
||||
*/
|
||||
serverinfo
|
||||
{
|
||||
/*
|
||||
* The hostname that Anope will be seen as, it must have no conflicts with any
|
||||
* other server names on the rest of your IRC network. Note that it does not have
|
||||
* to be an existing hostname, just one that isn't on your network already.
|
||||
*/
|
||||
name = "${services.host}"
|
||||
|
||||
/*
|
||||
* The text which should appear as the server's information in /WHOIS and similar
|
||||
* queries.
|
||||
*/
|
||||
description = "Anope IRC Statistics"
|
||||
|
||||
/*
|
||||
* The local address that Anope will bind to before connecting to the remote
|
||||
* server. This may be useful for multihomed hosts. If omitted, Anope will let
|
||||
* the Operating System choose the local address. This directive is optional.
|
||||
*
|
||||
* If you don't know what this means or don't need to use it, just leave this
|
||||
* directive commented out.
|
||||
*/
|
||||
#localhost = "nowhere."
|
||||
|
||||
/*
|
||||
* What Server ID to use for this connection?
|
||||
* Note: This should *ONLY* be used for TS6/P10 IRCds. Refer to your IRCd documentation
|
||||
* to see if this is needed.
|
||||
*/
|
||||
#id = "00A"
|
||||
|
||||
/*
|
||||
* The filename containing the Anope process ID. The path is relative to the
|
||||
* data directory.
|
||||
*/
|
||||
pid = "anope.pid"
|
||||
|
||||
/*
|
||||
* The filename containing the Message of the Day. The path is relative to the
|
||||
* config directory.
|
||||
*/
|
||||
motd = "motd.txt"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Protocol module
|
||||
*
|
||||
* This directive tells Anope which IRCd Protocol to speak when connecting.
|
||||
* You MUST modify this to match the IRCd you run.
|
||||
*
|
||||
* Supported:
|
||||
* - bahamut
|
||||
* - hybrid
|
||||
* - inspircd
|
||||
* - ngircd
|
||||
* - plexus
|
||||
* - ratbox
|
||||
* - solanum
|
||||
* - unrealircd
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "inspircd"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Network Information
|
||||
*
|
||||
* This section contains information about the IRC network that Anope will be
|
||||
* connecting to.
|
||||
*/
|
||||
networkinfo
|
||||
{
|
||||
/*
|
||||
* This is the name of the network that Anope will be running on.
|
||||
*/
|
||||
networkname = "LocalNet"
|
||||
|
||||
/*
|
||||
* Set this to the maximum allowed nick length on your network.
|
||||
* Be sure to set this correctly, as setting this wrong can result in
|
||||
* Anope being disconnected from the network. Defaults to 31.
|
||||
*/
|
||||
#nicklen = 31
|
||||
|
||||
/* Set this to the maximum allowed ident length on your network.
|
||||
* Be sure to set this correctly, as setting this wrong can result in
|
||||
* Anope being disconnected from the network. Defaults to 10.
|
||||
*/
|
||||
#userlen = 10
|
||||
|
||||
/* Set this to the maximum allowed hostname length on your network.
|
||||
* Be sure to set this correctly, as setting this wrong can result in
|
||||
* Anope being disconnected from the network. Defaults to 64.
|
||||
*/
|
||||
#hostlen = 64
|
||||
|
||||
/* Set this to the maximum allowed channel length on your network.
|
||||
* Defaults to 64.
|
||||
*/
|
||||
#chanlen = 32
|
||||
|
||||
/* The maximum number of list modes settable on a channel (such as b, e, I).
|
||||
* Comment out or set to 0 to disable.
|
||||
*/
|
||||
modelistsize = 100
|
||||
|
||||
/*
|
||||
* The characters allowed in hostnames. This is used for validating hostnames given
|
||||
* to services, such as BotServ bot hostnames and user vhosts. Changing this is not
|
||||
* recommended unless you know for sure your IRCd supports whatever characters you are
|
||||
* wanting to use. Telling services to set a vHost containing characters your IRCd
|
||||
* disallows could potentially break the IRCd and/or Anope.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
vhost_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-"
|
||||
|
||||
/*
|
||||
* If set to true, allows vHosts to not contain dots (.).
|
||||
* Newer IRCds generally do not have a problem with this, but the same warning as
|
||||
* vhost_chars applies.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
allow_undotted_vhosts = false
|
||||
|
||||
/*
|
||||
* The characters that are not allowed to be at the very beginning or very ending
|
||||
* of a vHost. The same warning as vhost_chars applies.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
disallow_start_or_end = ".-"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Anope Options
|
||||
*
|
||||
* This section contains various options which determine how Anope will operate.
|
||||
*/
|
||||
options
|
||||
{
|
||||
/*
|
||||
* On Linux/UNIX systems Anope can setuid and setgid to this user and group
|
||||
* after starting up. This is useful if Anope has to bind to privileged ports.
|
||||
*/
|
||||
#user = "anope"
|
||||
#group = "anope"
|
||||
|
||||
/*
|
||||
* The case mapping used by services. This must be set to a valid locale name
|
||||
* installed on your machine. Anope uses this case map to compare, with
|
||||
* case insensitivity, things such as nick names, channel names, etc.
|
||||
*
|
||||
* We provide two special casemaps shipped with Anope, ascii and rfc1459.
|
||||
*
|
||||
* This value should be set to what your IRCd uses, which is probably rfc1459,
|
||||
* however Anope has always used ascii for comparison, so the default is ascii.
|
||||
*
|
||||
* Changing this value once set is not recommended.
|
||||
*/
|
||||
casemap = "ascii"
|
||||
|
||||
/*
|
||||
* Sets the timeout period for reading from the uplink.
|
||||
*/
|
||||
readtimeout = 5s
|
||||
|
||||
/*
|
||||
* If set, Anope will only show /stats o to IRC Operators. This directive
|
||||
* is optional.
|
||||
*/
|
||||
#hidestatso = yes
|
||||
|
||||
/*
|
||||
* A space-separated list of U-lined servers on your network, it is assumed that
|
||||
* the servers in this list are allowed to set channel modes and Anope will
|
||||
* not attempt to reverse their mode changes.
|
||||
*
|
||||
* WARNING: Do NOT put your normal IRC user servers in this directive.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
#ulineservers = "services.your.network"
|
||||
|
||||
/*
|
||||
* How long to wait between connection retries with the uplink(s).
|
||||
*/
|
||||
retrywait = 60s
|
||||
}
|
||||
|
||||
/*
|
||||
* [RECOMMENDED] Logging Configuration
|
||||
*
|
||||
* This section is used for configuring what is logged and where it is logged to.
|
||||
* You may have multiple log blocks if you wish. Remember to properly secure any
|
||||
* channels you choose to have Anope log to!
|
||||
*/
|
||||
log
|
||||
{
|
||||
/*
|
||||
* Target(s) to log to, which may be one of the following:
|
||||
* - a channel name
|
||||
* - a filename
|
||||
* - globops
|
||||
*/
|
||||
target = "stats.log"
|
||||
|
||||
/* Log to both stats.log and the channel #stats
|
||||
*
|
||||
* Note that some older IRCds, such as Ratbox, require services to be in the
|
||||
* log channel to be able to message it. To do this, configure service:channels to
|
||||
* join your logging channel.
|
||||
*/
|
||||
#target = "stats.log #stats"
|
||||
|
||||
/*
|
||||
* The source(s) to only accept log messages from. Leave commented to allow all sources.
|
||||
* This can be a users name, a channel name, one of our clients (e.g. OperServ), or a server name.
|
||||
*/
|
||||
#source = ""
|
||||
|
||||
/*
|
||||
* The bot used to log generic messages which have no predefined sender if there
|
||||
* is a channel in the target directive.
|
||||
*/
|
||||
bot = "Global"
|
||||
|
||||
/*
|
||||
* The number of days to keep log files, only useful if you are logging to a file.
|
||||
* Set to 0 to never delete old log files.
|
||||
*
|
||||
* Note that Anope must run 24 hours a day for this feature to work correctly.
|
||||
*/
|
||||
logage = 7
|
||||
|
||||
/*
|
||||
* What types of log messages should be logged by this block. There are nine general categories:
|
||||
*
|
||||
* servers - Server actions, linking, squitting, etc.
|
||||
* channels - Actions in channels such as joins, parts, kicks, etc.
|
||||
* users - User actions such as connecting, disconnecting, changing name, etc.
|
||||
* other - All other messages without a category.
|
||||
* rawio - Logs raw input and output from services
|
||||
* debug - Debug messages (log files can become VERY large from this).
|
||||
*
|
||||
* These options determine what messages from the categories should be logged. Wildcards are accepted, and
|
||||
* you can also negate values with a ~. For example, "~operserv/akill operserv/*" would log all operserv
|
||||
* messages except for operserv/akill. Note that processing stops at the first matching option, which
|
||||
* means "* ~operserv/*" would log everything because * matches everything.
|
||||
*
|
||||
* Valid server options are:
|
||||
* connect, quit, sync, squit
|
||||
*
|
||||
* Valid channel options are:
|
||||
* create, destroy, join, part, kick, leave, mode
|
||||
*
|
||||
* Valid user options are:
|
||||
* connect, disconnect, quit, nick, ident, host, mode, maxusers, oper, away
|
||||
*
|
||||
* Rawio and debug are simple yes/no answers, there are no types for them.
|
||||
*
|
||||
* Note that modules may add their own values to these options.
|
||||
*/
|
||||
servers = "*"
|
||||
#channels = "~mode *"
|
||||
users = "connect disconnect nick"
|
||||
other = "*"
|
||||
rawio = no
|
||||
debug = no
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] MySQL Database configuration.
|
||||
*
|
||||
* mysql
|
||||
*
|
||||
* This module allows other modules to use MySQL.
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "mysql"
|
||||
|
||||
mysql
|
||||
{
|
||||
/* The name of this service. */
|
||||
name = "mysql/main"
|
||||
database = "anope"
|
||||
server = "127.0.0.1"
|
||||
username = "anope"
|
||||
password = "mypassword"
|
||||
port = 3306
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IRC2SQL Gateway
|
||||
* This module collects data about users, channels and servers. It doesn't build stats
|
||||
* itself, however, it gives you the database, it's up to you how you use it.
|
||||
*
|
||||
* Requires a MySQL Database and MySQL version 5.5 or higher
|
||||
*/
|
||||
include
|
||||
{
|
||||
type = "file"
|
||||
name = "irc2sql.example.conf"
|
||||
}
|
||||
+2
-2
@@ -22,9 +22,9 @@ contributions they have made, are:
|
||||
* Michael Wobst <wobst.michael@web.de>
|
||||
* Mark Summers <mark@goopler.net>
|
||||
* Matt Schatz <genius3000@g3k.solutions>
|
||||
* PeGaSuS <droider.pc@gmail.com>
|
||||
* Daniel Vassdal <shutter@canternet.org>
|
||||
* MatthewM <mcm@they-got.us>
|
||||
* PeGaSuS <droider.pc@gmail.com>
|
||||
* Sebastian V. <hal9000@denorastats.org>
|
||||
* Alvaro Toledo <atoledo@keldon.org>
|
||||
* Dragone2 <dragone2@risposteinformatiche.it>
|
||||
@@ -33,9 +33,9 @@ contributions they have made, are:
|
||||
* Hendrik Jäger <gitcommit@henk.geekmail.org>
|
||||
* k4be <k4be@pirc.pl>
|
||||
* Thomas Fargeix <t.fargeix@gmail.com>
|
||||
* Val Lorentz <progval+git@progval.net>
|
||||
* Bram Matthys <syzop@vulnscan.org>
|
||||
* Federico G. Schwindt <fgsch@lodoss.net>
|
||||
* Val Lorentz <progval+git@progval.net>
|
||||
* Alexander Barton <alex@barton.de>
|
||||
* CaPa CuL <capacul@gmail.com>
|
||||
* Cronus <cronus@nite-serv.com>
|
||||
|
||||
+73
-2
@@ -1,5 +1,76 @@
|
||||
Anope Version 2.1.14-git
|
||||
------------------------
|
||||
Anope Version 2.1.18
|
||||
--------------------
|
||||
Added a check that a non-deprecated database module is loaded.
|
||||
Added support for flexible and monospace layouts to make text easier to read on clients that use a variable-width font.
|
||||
Added support for logging about deprecated modules on boot.
|
||||
Added support for per-IRCd hints when a link fails.
|
||||
Added support for self-service validation of vhosts using DNS TXT records.
|
||||
Added support for separate bad password limits for pre-connection SASL authentication.
|
||||
Added support for SRV and TXT records to the dns module.
|
||||
Added the --nodb option to disable database and encrytption module checks.
|
||||
Added the nickname registration date to the nickserv/glist output.
|
||||
Changed db_flatfile to be import-only (migrate to db_json).
|
||||
Changed the default registration confirmation type to code validation.
|
||||
Changed the fantasy !help command to not require the FANTASY privilege by default.
|
||||
Changed various length measurement code to be UTF-8 aware.
|
||||
Disabled the nickname registration delay by default.
|
||||
Fixed reporting the MySQL version that the mysql module was built against.
|
||||
Improved the layout of the nickserv/info command.
|
||||
Modularised the ns_sasl module to make it easier to pick SASL mechanisms.
|
||||
Moved duration rounding logic from Anope::Expires to Anope::Duration.
|
||||
Removed support for importing old databases from 1.8.
|
||||
Removed support for verifying "old MD5" passwords from 1.7.
|
||||
Reworked how memory is allocated when formatting messages.
|
||||
|
||||
Anope Version 2.1.17
|
||||
--------------------
|
||||
Allowed opers to resend passwords for users in nickserv/resend.
|
||||
Fixed HostServ using a different valid username character set to the protocol module.
|
||||
Fixed losing the channel and nickname registration time when upgrading from an earlier 2.1 release.
|
||||
Improved the messages sent when a user is forced off a protected nickname.
|
||||
Simplified copying modules to the runtime directory on Windows.
|
||||
|
||||
Anope Version 2.1.16
|
||||
--------------------
|
||||
Added support for on-IRC code confirmation.
|
||||
Added the ability for fantasy commands to be executable without the FANTASY privilege.
|
||||
Added the ability to prepend to topics as well as appending to them.
|
||||
Changed various fields to serialize to the database as a string not an integer.
|
||||
Disabled db_flatfile by default in preparation for becoming import-only.
|
||||
Fixed a memory leak in the db_json module.
|
||||
Fixed building on OpenSSL 1.1.1 (for now).
|
||||
Fixed removed and later re-added temporary bans being removed automatically.
|
||||
Fixed sometimes sending malformed LMODE messages on InspIRCd.
|
||||
Fixed the "did you mean" message suggesting unloaded commands.
|
||||
Fixed various issues with the example config files.
|
||||
Marked db_json as the recommended database module.
|
||||
Moved the BAN, UNBAN, and KICK commands to the chanserv/management group.
|
||||
Removed support for the 1.8-style seen command.
|
||||
Reworked confirmation to allow confirmation of multiple account actions.
|
||||
When dropping a display nickname the new display will now be the oldest in the group.
|
||||
|
||||
Anope Version 2.1.15
|
||||
--------------------
|
||||
Added a workaround to the jsonrpc module for JavaScript truncating big integers.
|
||||
Added an example Ruby library for accessing the RPC interface.
|
||||
Added away state and tls usage to the anope.user RPC event.
|
||||
Added support for looking up accounts by identifier in the anope.account RPC event.
|
||||
Added support for storing the setter and set time and setter of list modes and restoring them on InspIRCd and Solanum.
|
||||
Added support for token authentication to the RPC modules.
|
||||
Added the anope.checkCredentials, anope.identify, anope.listCommands, and anope.command RPC events to the new rpc_user module.
|
||||
Bumped the minimum supported version of ircd-hybrid to 8.2.34.
|
||||
Deprecated irc2sql in favour of rpc_data.
|
||||
Dropped support for Bahamut as it has no known users.
|
||||
Fixed creating duplicate Stats rows on some servers.
|
||||
Fixed loading databases in db_json.
|
||||
Fixed restoring cloaked hosts on InspIRCd when the cloak module is not loaded.
|
||||
Fixed some variable shadowing that potentially caused issues with the SQL database backends.
|
||||
Fixed sometimes writing accounts to the database without a unique identifier.
|
||||
Fixed various documentation issues with the example JavaScript JSON-RPC client.
|
||||
Improved CTCP handling and added support for more CTCP types.
|
||||
|
||||
Anope Version 2.1.14
|
||||
--------------------
|
||||
Added a detail specifier to the anope.list{Channels,Opers,Servers,Users} RPC methods.
|
||||
Added a matcher for the InspIRCd oper extban.
|
||||
Added support for hashed operator passwords.
|
||||
|
||||
+63
-6
@@ -1,5 +1,62 @@
|
||||
Anope Version 2.1.14-git
|
||||
------------------------
|
||||
Anope Version 2.1.18
|
||||
--------------------
|
||||
Added the hostserv/validate command.
|
||||
Added the nickserv/saset/layout command.
|
||||
Added the nickserv/set/layout command.
|
||||
Added the ns_sasl_anonymous module.
|
||||
Added the ns_sasl_external module.
|
||||
Added the ns_sasl_plain module.
|
||||
Added the ns_set_layout module.
|
||||
Added the ns_set_op module.
|
||||
Added {hs_request}:validationcooldown (defaults to 5 minutes).
|
||||
Added {hs_request}:validationrecord (defaults to "anope-dns-validation").
|
||||
Added {ns_sasl}:badpasslimit (defaults to options:badpasslimit).
|
||||
Added {ns_sasl}:badpasstimeout (defaults to options:badpasstimeout).
|
||||
Moved nickserv/set/autoop and nickserv/saset/autoop to the ns_set_op module.
|
||||
Moved nickserv/set/display and nickserv/saset/display to the ns_set_group module.
|
||||
Moved nickserv/set/neverop and nickserv/saset/neverop to the ns_set_op module.
|
||||
Removed the db_old module.
|
||||
Removed the enc_old module.
|
||||
Removed {db_flatfile}:fork (module is now import-only).
|
||||
Removed {db_flatfile}:keepbackups (module is now import-only).
|
||||
Removed {db_flatfile}:nobackupokay (module is now import-only).
|
||||
|
||||
Anope Version 2.1.17
|
||||
--------------------
|
||||
Added the nickserv/resend oper privilege.
|
||||
|
||||
Anope Version 2.1.16
|
||||
--------------------
|
||||
Added fantasy:require_privilege (defaults to yes).
|
||||
Added the nickserv/confirm/email command.
|
||||
Added the nickserv/confirm/email oper privilege.
|
||||
Added the nickserv/confirm/register command.
|
||||
Added the ns_confirm module.
|
||||
Added {ns_email}:changeexpire (defaults to 1 day).
|
||||
Added {ns_resetpass}:resetexpire (defaults to 1 day).
|
||||
Removed the irc2sql module (migrate to JSON-RPC instead).
|
||||
Removed {ns_seen}:simple (1.8-style seen has been removed).
|
||||
Renamed the nickserv/confirm oper privilege to nickserv/confirm/register.
|
||||
|
||||
Anope Version 2.1.15
|
||||
--------------------
|
||||
Added the ns_email module.
|
||||
Added the rpc_user module.
|
||||
Added {jsonrpc}:integer_bits (defaults to 64).
|
||||
Added {jsonrpc}:token.
|
||||
Added {nickserv}:enforcerreal (defaults to "Services Enforcer").
|
||||
Added {xmlrpc}:token.
|
||||
Moved nickserv/set/email and nickserv/saset/email to the ns_email module.
|
||||
Removed the bahamut module.
|
||||
Removed the ns_getemail module (load ns_email instead).
|
||||
Removed the ns_maxemail module (load ns_email instead).
|
||||
Removed the rpc_main module (migrate to the other RPC modules).
|
||||
Removed {chanstats}:cs_def_chanstats (add CS_STATS to {chanserv}:defaults instead).
|
||||
Removed {chanstats}:ns_def_chanstats (add NS_STATS to {nickserv}:defaults instead).
|
||||
Renamed service:gecos to service:real.
|
||||
|
||||
Anope Version 2.1.14
|
||||
--------------------
|
||||
Added oper:password_hash.
|
||||
Added options:codelength (defaults to 15).
|
||||
Added {os_news}:showdate (defaults to yes).
|
||||
@@ -8,7 +65,7 @@ Added {sql_authentication}:password_hash.
|
||||
Changed the default value for options:linelength to "100".
|
||||
Changed the default value for {enc_sha2}:algorithm to "sha512".
|
||||
Changed the default value for {ns_seen}:purgetime to "90d".
|
||||
Changed the syntax for template variables in mail:emailchange_message, mail:emailchange_subject, mail:memo_message, mail:memo_subject, mail:registration_message, mail:registration_subject,, mail:reset_message, mail:reset_subject, {chanserv}:signkickformat, {dnsbl}:blacklist:reason, {ldap_authentication}:search_filter, {ldap_oper}:binddn, {ldap_oper}:search_filter, {nickserv}:unregistered_notice, {os_session}:sessionlimitexceeded, {proxyscan}:proxyscan:reason.
|
||||
Changed the syntax for template variables in mail:emailchange_message, mail:emailchange_subject, mail:memo_message, mail:memo_subject, mail:registration_message, mail:registration_subject, mail:reset_message, mail:reset_subject, {chanserv}:signkickformat, {dnsbl}:blacklist:reason, {ldap_authentication}:search_filter, {ldap_oper}:binddn, {ldap_oper}:filter, {nickserv}:unregistered_notice, {os_session}:sessionlimitexceeded, {proxyscan}:proxyscan:reason.
|
||||
|
||||
Anope Version 2.1.13
|
||||
--------------------
|
||||
@@ -134,13 +191,13 @@ Removed the m_regex_pcre module (use m_regex_pcre2 instead).
|
||||
|
||||
Anope Version 2.1.0
|
||||
-------------------
|
||||
Added nickserv:minpasslen for configuring the minimum password length (defaults to 8).
|
||||
Removed nickserv:strictpasswords (obsolete now nickserv:minpasslen exists).
|
||||
Added {nickserv}:minpasslen for configuring the minimum password length (defaults to 8).
|
||||
Removed {nickserv}:strictpasswords (obsolete now {nickserv}:minpasslen exists).
|
||||
Removed the inspircd12 and inspircd20 modules (use inspircd instead).
|
||||
Removed the ns_getpass module (no supported encryption modules).
|
||||
Removed the os_oline module (no supported IRCds).
|
||||
Removed the unreal module (use unrealircd instead).
|
||||
Renamed nickserv:passlen to nickserv:maxpasslen.
|
||||
Renamed {nickserv}:passlen to {nickserv}:maxpasslen.
|
||||
Renamed the charybdis module to solanum.
|
||||
Renamed the inspircd3 module to inspircd.
|
||||
Renamed the unreal4 module to unrealircd.
|
||||
|
||||
+4
-1
@@ -29,11 +29,14 @@ Anope Multi Language Support
|
||||
install gettext and run `msginit -l language -o anope.language.po -i anope.pot`. For example if I was translating to
|
||||
Spanish I could run `msginit -l es_ES -o anope.es_ES.po -i anope.pot`. Open the newly generating .po file and start
|
||||
translating. Once you are done simply rerun ./Config; make && make install and add the language to your anope.conf.
|
||||
Note that on Windows it is not quite this simple, windows.cpp must be edited and Anope recompiled and restarted.
|
||||
|
||||
Poedit (https://poedit.net/) is a popular po file editor, and we recommend using it or another editor designed to edit
|
||||
po files (especially on Windows).
|
||||
|
||||
There are several control characters within the messages. These are mostly IRC formatting codes (https://modern.ircdocs.horse/formatting)
|
||||
but 0x1A is special to Anope and is used to prevent the automatic linewrapper from breaking messages in the middle of
|
||||
text that should not be split (e.g. commands). Your editor may not show these so be careful you don't delete them!
|
||||
|
||||
If you have finished a language file translation and you want others to use it, please file a pull request on GitHub
|
||||
or send it to team@anope.org (don't forget to mention clearly your (nick)name, your email and the language name).
|
||||
You'll of course get full credit for it.
|
||||
|
||||
+2
-3
@@ -160,15 +160,14 @@ Table of Contents
|
||||
they log on, to set modes and to kick users from any channel, to
|
||||
send notices quickly to the entire network, and much more!
|
||||
|
||||
* HostServ, a neat service that allows users to show custom vHosts
|
||||
* HostServ, a neat service that allows users to show custom vhosts
|
||||
(virtual hosts) instead of their real IP address; this only works
|
||||
on daemons supporting ip cloaking, such as UnrealIRCd.
|
||||
|
||||
Anope currently works with:
|
||||
|
||||
* Bahamut 2.0 or later
|
||||
* InspIRCd 3 or later
|
||||
* ircd-hybrid 8.2.23 or later
|
||||
* ircd-hybrid 8.2.34 or later
|
||||
* ircd-ratbox 3 or later
|
||||
* ngIRCd 19.2 or later
|
||||
* Plexus 3 or later
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
RPC using JSON-RPC and XML-RPC (using PECL's xmlrpc_encode_request and xmlrpc_decode functions) is supported.
|
||||
|
||||
This allows external applications, such as websites, to execute remote procedure calls to Anope in real time.
|
||||
|
||||
Currently there are 5 supported RPC calls, provided by rpc_main:
|
||||
|
||||
checkAuthentication - Takes two parameters, an account name and a password. Checks if the account name is valid and the password
|
||||
is correct for the account name, useful for making login pages on websites.
|
||||
|
||||
command - Takes three parameters, a service name (BotServ, ChanServ, NickServ), a user name (whether online or not), and the command
|
||||
to execute. This will execute the given command to Anope using the given service name. If the user given is online, the
|
||||
command reply will go to them, if not it is returned by RPC.
|
||||
|
||||
stats - Takes no parameters, returns miscellaneous stats that can be found in the /operserv stats command.
|
||||
|
||||
RPC was designed to be used with db_sql, and will not return any information that can be pulled from the SQL
|
||||
database, such as accounts and registered channel information. It is instead used for pulling realtime data such
|
||||
as users and channels currently online. For examples on how to use these calls in PHP, see xmlrpc.php in docs/RPC.
|
||||
|
||||
Also note that when using XMLRPC the parameter named "id" is reserved for query ID. If you pass a query to Anope containing a value for id. it will
|
||||
be stored by Anope and the same id will be passed back in the result.
|
||||
+75
-16
@@ -7,10 +7,12 @@ class AnopeRPC {
|
||||
/**
|
||||
* Initializes a new AnopeRPC instance with the specified RPC host.
|
||||
*
|
||||
* @param {string} The RPC host base URL.
|
||||
* @param {string} host The RPC host base URL.
|
||||
* @param {string} token The bearer token for authorizing with the RPC interface.
|
||||
*/
|
||||
constructor(host) {
|
||||
constructor(host, token = "") {
|
||||
this.host = host;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,15 +23,20 @@ class AnopeRPC {
|
||||
* @returns {*} The result of the RPC query.
|
||||
*/
|
||||
async run(method, ...params) {
|
||||
const request = JSON.stringify({
|
||||
const body = JSON.stringify({
|
||||
"jsonrpc": "2.0",
|
||||
"method": method,
|
||||
"params": params,
|
||||
"params": params.map((p) => p.toString()),
|
||||
"id": Math.random().toString(36).slice(2)
|
||||
});
|
||||
const headers = new Headers();
|
||||
if (this.token) {
|
||||
headers.append("Authorization", `Bearer ${btoa(this.token)}`);
|
||||
}
|
||||
const response = await fetch(this.host, {
|
||||
method: 'POST',
|
||||
body: request
|
||||
headers: headers,
|
||||
body: body
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP returned ${response.status}`)
|
||||
@@ -49,8 +56,8 @@ class AnopeRPC {
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of account names.
|
||||
* @param {string} detail The level of detail to request.
|
||||
* @returns {(array|object)} A list of accounts.
|
||||
*/
|
||||
listAccounts(detail = "name") {
|
||||
return this.run("anope.listAccounts", detail);
|
||||
@@ -73,8 +80,8 @@ class AnopeRPC {
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of channel names.
|
||||
* @param {string} detail The level of detail to request.
|
||||
* @returns {(array|object)} A list of channels.
|
||||
*/
|
||||
listChannels(detail = "name") {
|
||||
return this.run("anope.listChannels", detail);
|
||||
@@ -97,8 +104,8 @@ class AnopeRPC {
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of channel names.
|
||||
* @param {string} detail The level of detail to request.
|
||||
* @returns {(array|object)} A list of services operators.
|
||||
*/
|
||||
listOpers(detail = "name") {
|
||||
return this.run("anope.listOpers", detail);
|
||||
@@ -121,8 +128,8 @@ class AnopeRPC {
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of servers names.
|
||||
* @param {string} detail The level of detail to request.
|
||||
* @returns {(array|object)} A list of servers.
|
||||
*/
|
||||
listServers(detail = "name") {
|
||||
return this.run("anope.listServers", detail);
|
||||
@@ -145,8 +152,8 @@ class AnopeRPC {
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of channel names.
|
||||
* @param {string} detail The level of detail to request.
|
||||
* @returns {(array|object)} A list of users.
|
||||
*/
|
||||
listUsers(detail = "name") {
|
||||
return this.run("anope.listUsers", detail);
|
||||
@@ -199,11 +206,63 @@ class AnopeRPC {
|
||||
messageUser(source, target, ...messages) {
|
||||
return this.run("anope.messageUser", source, target, ...messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the specified credentials are valid.
|
||||
*
|
||||
* Requires the rpc_user module to be loaded.
|
||||
*
|
||||
* @param {string} account A nickname belonging to the account to check.
|
||||
* @param {string} password The password for the specified account.
|
||||
* @returns {object} An object containing basic information about the account.
|
||||
*/
|
||||
checkCredentials(account, password) {
|
||||
return this.run("anope.checkCredentials", account, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies an IRC user to the specified account.
|
||||
*
|
||||
* Requires the rpc_user module to be loaded.
|
||||
*
|
||||
* @param {string} account Either an account identifier or nickname belonging to the account to
|
||||
* identify to.
|
||||
* @param {string} password The nickname of the IRC user to identify to the account.
|
||||
*/
|
||||
identify(account, user) {
|
||||
return this.run("anope.identify", account, user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all commands that exist on the network.
|
||||
*
|
||||
* Requires the rpc_user module to be loaded.
|
||||
*
|
||||
* @param {...*} services The nicknames of the services to list commands for.
|
||||
* @returns {object} An object containing information about the available commands.
|
||||
*/
|
||||
listCommands(...services) {
|
||||
return this.run("anope.listCommands", ...services);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all commands that exist on the network.
|
||||
*
|
||||
* Requires the rpc_user module to be loaded.
|
||||
*
|
||||
* @param {string} account If non-empty then the account to execute the command as.
|
||||
* @param {string} service The service which the command exists on.
|
||||
* @param {...*} command The the command to execute and any parameters to pass to it.
|
||||
* @returns {object} An object containing information about the available commands.
|
||||
*/
|
||||
command(account, service, ...command) {
|
||||
return this.run("anope.command", account, service, ...command);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
const arpc = new AnopeRPC("http://127.0.0.1:8080/jsonrpc");
|
||||
arpc.listServers().then(servers => {
|
||||
arpc.listServers("full").then(servers => {
|
||||
console.log(servers);
|
||||
}).catch (error => {
|
||||
console.log(error);
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* JSON-RPC functions
|
||||
*
|
||||
* (C) 2003-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*/
|
||||
|
||||
class AnopeRPC
|
||||
{
|
||||
/**
|
||||
* The RPC host
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* Initiate a new AnopeRPC instance
|
||||
*
|
||||
* @param $host
|
||||
*/
|
||||
public function __construct($host)
|
||||
{
|
||||
$this->host = $host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an RPC command. Name should be a query name and params an array of parameters, eg:
|
||||
* $this->raw("checkAuthentication", ["adam", "qwerty"]);
|
||||
* If successful returns back an array of useful information.
|
||||
*
|
||||
* Note that $params["id"] is reserved for query ID, you may set it to something if you wish.
|
||||
* If you do, the same ID will be passed back with the reply from Anope.
|
||||
*
|
||||
* @param $name
|
||||
* @param $params
|
||||
* @return array|null
|
||||
*/
|
||||
public function run($name, $params)
|
||||
{
|
||||
$request = json_encode([
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => uniqid(),
|
||||
"method" => $name,
|
||||
"params" => $params,
|
||||
]);
|
||||
$context = stream_context_create(["http" => [
|
||||
"method" => "POST",
|
||||
"header" => "Content-Type: application/json",
|
||||
"content" => $request]]);
|
||||
|
||||
$inbuf = file_get_contents($this->host, false, $context);
|
||||
$response = json_decode($inbuf, true);
|
||||
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Command on Service as User, eg:
|
||||
* $anope->command("ChanServ", "Adam", "REGISTER #adam");
|
||||
* Returns an array of information regarding the command execution, if
|
||||
* If 'online' is set to yes, then the reply to the command was sent to the user on IRC.
|
||||
* If 'online' is set to no, then the reply to the command is in the array member 'return'
|
||||
*
|
||||
* @param $service
|
||||
* @param $user
|
||||
* @param $command
|
||||
* @return array|null
|
||||
*/
|
||||
public function command($service, $user, $command)
|
||||
{
|
||||
return $this->run("command", [$service, $user, $command]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an account/nick name and password to see if they are valid
|
||||
* Returns the account display name if valid
|
||||
*
|
||||
* @param $account
|
||||
* @param $pass
|
||||
* @return string|null
|
||||
*/
|
||||
public function auth($account, $pass)
|
||||
{
|
||||
$ret = $this->run("checkAuthentication", [$account, $pass]);
|
||||
|
||||
if ($ret && array_key_exists("result", $ret) && array_key_exists("account", $ret["result"])) {
|
||||
return $ret["result"]["account"];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of misc stats regarding Anope
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function stats()
|
||||
{
|
||||
return $this->run("stats", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up data for a channel
|
||||
* Returns an array containing channel information, or an array of size one
|
||||
* (just containing the name) if the channel does not exist
|
||||
*
|
||||
* @param $channel
|
||||
* @return array|null
|
||||
*/
|
||||
public function channel($channel)
|
||||
{
|
||||
return $this->run("anope.channel", [$channel]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sent a notice to a user.
|
||||
* Returns an array containing channel information, or an array of size one
|
||||
* (just containing the name) if the channel does not exist
|
||||
*
|
||||
* @param $source
|
||||
* @param $target
|
||||
* @param $message
|
||||
* @return array|null
|
||||
*/
|
||||
public function notice($source, $target, $message)
|
||||
{
|
||||
return $this->run("anope.messageUser", [$source, $target, $message]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like channel(), but different.
|
||||
*
|
||||
* @param $user
|
||||
* @return array|null
|
||||
*/
|
||||
public function user($user)
|
||||
{
|
||||
return $this->run("anope.user", [$user]);
|
||||
}
|
||||
}
|
||||
|
||||
$anope = new AnopeRPC("http://127.0.0.1:8080/jsonrpc");
|
||||
@@ -0,0 +1,242 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
require "base64"
|
||||
require "json"
|
||||
require "net/http"
|
||||
|
||||
# Implements methods for accessing an Anope JSON-RPC server.
|
||||
class AnopeRPC
|
||||
|
||||
# The RPC host base URL.
|
||||
attr_accessor :host
|
||||
|
||||
# The bearer token for authorizing with the RPC interface.
|
||||
attr_accessor :token
|
||||
|
||||
# Initializes a new AnopeRPC instance with the specified RPC host.
|
||||
#
|
||||
# @param host [String] The RPC host base URL.
|
||||
# @param token [String] The bearer token for authorizing with the RPC interface.
|
||||
def initialize(host, token = nil)
|
||||
@host = URI(host)
|
||||
@token = token
|
||||
end
|
||||
|
||||
# Executes an arbitrary RPC query.
|
||||
#
|
||||
# @param method [String] The name of the method to execute.
|
||||
# @param params [Object] The parameters pass to the method.
|
||||
# @return [Object] The result of the RPC query.
|
||||
private def run(method, *params)
|
||||
body = {
|
||||
jsonrpc: "2.0",
|
||||
method: method,
|
||||
params: params.map(&:to_s),
|
||||
id: rand(36**16).to_s(36)
|
||||
}.to_json
|
||||
|
||||
headers = {}
|
||||
headers["Authorization"] = "Bearer #{Base64.strict_encode64(@token)}" if @token
|
||||
|
||||
response = Net::HTTP.post(@host, body, headers)
|
||||
raise "HTTP returned #{response.status}" unless response.is_a?(Net::HTTPSuccess)
|
||||
|
||||
json = JSON.parse(response.body, symbolize_names: true)
|
||||
raise "JSON-RPC returned #{json[:error][:code]}: #{json[:error][:message]}" if json.key?(:error)
|
||||
|
||||
json.dig(:result)
|
||||
end
|
||||
|
||||
# Retrieves a list of accounts.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param detail [Symbol] detail The level of detail to request.
|
||||
# @return [Array] If the detail level is set to :name then an array of account names.
|
||||
# @return [Hash] If the detail level is set to :full then a hash of information about the
|
||||
# accounts.
|
||||
def list_accounts(detail = :name)
|
||||
self.run("anope.listAccounts", detail)
|
||||
end
|
||||
|
||||
# Retrieves information about the specified account.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param name [String] The name of the account.
|
||||
# @return [Hash] A hash containing information about the account.
|
||||
def account(name)
|
||||
self.run("anope.account", name)
|
||||
end
|
||||
|
||||
# Retrieves a list of channels.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param detail [Symbol] detail The level of detail to request.
|
||||
# @return [Array] If the detail level is set to :name then an array of channel names.
|
||||
# @return [Hash] If the detail level is set to :full then a hash of information about the
|
||||
# channels.
|
||||
def list_channels(detail = :name)
|
||||
self.run("anope.listChannels", detail)
|
||||
end
|
||||
|
||||
# Retrieves information about the specified channel.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param name [String] The name of the channel.
|
||||
# @return [Hash] A hash containing information about the channel.
|
||||
def channel(name)
|
||||
self.run("anope.channel", name)
|
||||
end
|
||||
|
||||
# Retrieves a list of services operators.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param detail [Symbol] detail The level of detail to request.
|
||||
# @return [Array] If the detail level is set to :name then an array of services operator names.
|
||||
# @return [Hash] If the detail level is set to :full then a hash of information about the
|
||||
# services operators.
|
||||
def list_opers(detail = :name)
|
||||
self.run("anope.listOpers", detail)
|
||||
end
|
||||
|
||||
# Retrieves information about the specified services operator.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param name [String] The name of the services operator.
|
||||
# @return [Hash] A hash containing information about the services operator.
|
||||
def oper(name)
|
||||
self.run("anope.oper", name)
|
||||
end
|
||||
|
||||
# Retrieves a list of servers.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param detail [Symbol] detail The level of detail to request.
|
||||
# @return [Array] If the detail level is set to :name then an array of server names.
|
||||
# @return [Hash] If the detail level is set to :full then a hash of information about the
|
||||
# servers.
|
||||
def list_servers(detail = :name)
|
||||
self.run("anope.listServers", detail)
|
||||
end
|
||||
|
||||
# Retrieves information about the specified server.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param name [String] The name of the server.
|
||||
# @return [Hash] A hash containing information about the server.
|
||||
def server(name)
|
||||
self.run("anope.server", name)
|
||||
end
|
||||
|
||||
# Retrieves a list of users.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param detail [Symbol] detail The level of detail to request.
|
||||
# @return [Array] If the detail level is set to :name then an array of user nicknames.
|
||||
# @return [Hash] If the detail level is set to :full then a hash of information about the
|
||||
# users.
|
||||
def list_users(detail = :name)
|
||||
self.run("anope.listUsers", detail)
|
||||
end
|
||||
|
||||
# Retrieves information about the specified user.
|
||||
#
|
||||
# Requires the rpc_data module to be loaded.
|
||||
#
|
||||
# @param name [String] The name of the user.
|
||||
# @return [Hash] A hash containing information about the user.
|
||||
def user(name)
|
||||
self.run("anope.user", name)
|
||||
end
|
||||
|
||||
# Sends a message to every user on the network.
|
||||
#
|
||||
# Requires the rpc_message module to be loaded.
|
||||
#
|
||||
# @param messages [Array<String>] One or more messages to send.
|
||||
def message_network(*messages)
|
||||
self.run("anope.messageNetwork", *messages)
|
||||
end
|
||||
|
||||
# Sends a message to every user on the specified server.
|
||||
#
|
||||
# Requires the rpc_message module to be loaded.
|
||||
#
|
||||
# @param name [String] The name of the server.
|
||||
# @param messages [Array<String>] One or more messages to send.
|
||||
def message_server(server, *messages)
|
||||
self.run("anope.messageServer", server, *messages)
|
||||
end
|
||||
|
||||
# Sends a message to the specified user.
|
||||
#
|
||||
# Requires the rpc_message module to be loaded.
|
||||
#
|
||||
# @param source [String] The source pseudoclient to send the message from.
|
||||
# @param target [String] The target user to send the message to.
|
||||
# @param messages [Array<String>] One or more messages to send.
|
||||
def message_user(source, target, *messages)
|
||||
self.run("anope.messageUser", source, target, *messages)
|
||||
end
|
||||
|
||||
# Checks whether the specified credentials are valid.
|
||||
#
|
||||
# Requires the rpc_user module to be loaded.
|
||||
#
|
||||
# @param account [String] A nickname belonging to the account to check.
|
||||
# @param password [String] The password for the specified account.
|
||||
# @return [Hash] A hash containing basic information about the account.
|
||||
def check_credentials(account, password)
|
||||
self.run("anope.checkCredentials", account, password)
|
||||
end
|
||||
|
||||
# Identifies an IRC user to the specified account.
|
||||
#
|
||||
# Requires the rpc_user module to be loaded.
|
||||
#
|
||||
# @param account [String] Either an account identifier or nickname belonging to the account to
|
||||
# identify to.
|
||||
# @param password [String] The nickname of the IRC user to identify to the account.
|
||||
def identify(account, user)
|
||||
self.run("anope.identify", account, user)
|
||||
end
|
||||
|
||||
# Lists all commands that exist on the network.
|
||||
#
|
||||
# Requires the rpc_user module to be loaded.
|
||||
#
|
||||
# @param services [Array<String>] The nicknames of the services to list commands for.
|
||||
# @return [Hash] A hash containing information about the available commands.
|
||||
def list_commands(*services)
|
||||
self.run("anope.listCommands", *services)
|
||||
end
|
||||
|
||||
# Lists all commands that exist on the network.
|
||||
#
|
||||
# Requires the rpc_user module to be loaded.
|
||||
#
|
||||
# @param account [String] If non-empty then the account to execute the command as.
|
||||
# @param service [String] The service which the command exists on.
|
||||
# @param command [Array<String>] The the command to execute and any parameters to pass to it.
|
||||
# @return [Hash] A hash containing information about the available commands.
|
||||
def command(account, service, *command)
|
||||
self.run("anope.command", account, service, *command)
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
arpc = AnopeRPC.new("http://127.0.0.1:8080/jsonrpc")
|
||||
begin
|
||||
pp arpc.list_servers(:full)
|
||||
rescue StandardError => err
|
||||
STDERR.puts err
|
||||
end
|
||||
=end
|
||||
@@ -36,7 +36,7 @@ Retrieves information about the specified account.
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | A nickname belonging to the account.
|
||||
0 | Either a nickname belonging to the account or an account identifier.
|
||||
|
||||
### Errors
|
||||
|
||||
@@ -414,6 +414,9 @@ account.display | string | The display nickname of the account.
|
||||
account.opertype | string or null | The account's oper type or null if the account is not a services operator.
|
||||
account.uniqueid | uint | The unique immutable identifier of the account.
|
||||
address | string | The IP address the user is connecting from.
|
||||
away | map or null | The user's away state or null if they are not away.
|
||||
away.message | string | The away message specified by the user.
|
||||
away.time | int | The UNIX time at which the user went away.
|
||||
channels | array[string] | The channels that the user is in prefixed by their status mode prefixes.
|
||||
chost | string or null | The cloaked hostname of the user or null if they have no cloak.
|
||||
fingerprint | string or null | The fingerprint of the user's client certificate or null if they are not using one.
|
||||
@@ -425,6 +428,7 @@ nickchanged | int | The time at which the user last changed thei
|
||||
real | string | The real name of the user.
|
||||
server | string | The server that the user is connected to.
|
||||
signon | int | The time at which the user connected to the network.
|
||||
tls | bool | Whether the user is connected using TLS (SSL).
|
||||
uid | string or null | The unique immutable identifier of the user or null if the IRCd does not use UIDs.
|
||||
vhost | string or null | The virtual host of the user or null if they have no vhost.
|
||||
vident | string or null | The virtual ident (username) of the user or null if they have no vident.
|
||||
@@ -438,7 +442,8 @@ vident | string or null | The virtual ident (username) of the user or
|
||||
"opertype": "Services Root",
|
||||
"uniqueid": "17183514657819486040"
|
||||
},
|
||||
"address": "127.0.0.1",
|
||||
"address": "127.0.0.1",
|
||||
"away": null,
|
||||
"channels": ["@#chan1", "#chan2"],
|
||||
"chost": "localhost",
|
||||
"fingerprint": null,
|
||||
@@ -451,6 +456,7 @@ vident | string or null | The virtual ident (username) of the user or
|
||||
"real": "An IRC User",
|
||||
"server": "irc.example.com",
|
||||
"signon": 1740408296,
|
||||
"tls": true,
|
||||
"vhost": "staff.example.com",
|
||||
"vident": null,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
# Anope `rpc_user` RPC interface
|
||||
|
||||
## `anope.checkCredentials`
|
||||
|
||||
Checks whether the specified credentials are valid.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | A nickname belonging to the account to check.
|
||||
1 | The password for the specified account.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified account does not exist.
|
||||
-32098 | The specified password is not correct.
|
||||
-32097 | The specified account is suspended.
|
||||
|
||||
### Result
|
||||
|
||||
Returns a map containing basic information about the account. More information about the account can be found by calling [the `anope.account` event using the value from the `uniqueid` field (requires the rpc_data module)](./rpc_user.md).
|
||||
|
||||
Key | Type | Description
|
||||
--- | ---- | -----------
|
||||
account | string | The display nickname of the account.
|
||||
confirmed | boolean | Whether the account has been confirmed.
|
||||
uniqueid | uint | The unique immutable identifier of the account.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"account": "foo",
|
||||
"confirmed": true,
|
||||
"uniqueid": 11085415958920757000,
|
||||
}
|
||||
```
|
||||
|
||||
## `anope.identify`
|
||||
|
||||
Identifies an IRC user to the specified account.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | Either an account identifier or nickname belonging to the account to identify to.
|
||||
1 | The nickname of the IRC user to identify to the account.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified account does not exist.
|
||||
-32098 | The specified IRC user does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
This procedure returns no result.
|
||||
|
||||
## `anope.listCommands`
|
||||
|
||||
Lists all commands that exist on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0...n | The nicknames of the services to list commands for. If none are specified then all commands are returned.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32098 | The specified service does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
Returns a map containing information about the available commands.
|
||||
|
||||
Key | Type | Description
|
||||
--- | ---- | -----------
|
||||
\* | map | A key-value map of services to the commands that exist on them.
|
||||
\*.\* | string | A key-value map of commands to information about the commands.
|
||||
\*.\*.group | string or null | The group that the command belongs to or null if the command is not grouped.
|
||||
\*.\*.hidden | boolean | Whether the command is visible in the help output.
|
||||
\*.\*.maxparams | uint or null | The maximum number of parameters that the command accepts or null if there is no limit.
|
||||
\*.\*.minparams | uint | The minimum number of parameters that the command accepts.
|
||||
\*.\*.permission | string or null | The services operator permission required to execute the command or null if no permissions are required.
|
||||
\*.\*.requiresaccount | boolean | Whether a caller must be logged into an account to execute the command.
|
||||
\*.\*.requiresuser | boolean | Whether an IRC user is required to execute the command.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"Global": {
|
||||
"GLOBAL": {
|
||||
"group": null,
|
||||
"hidden": false,
|
||||
"maxparams": 1,
|
||||
"minparams": 0,
|
||||
"permission": "global/global",
|
||||
"requiresaccount": true,
|
||||
"requiresuser": false
|
||||
},
|
||||
"HELP": {
|
||||
"group": null,
|
||||
"hidden": false,
|
||||
"maxparams": null,
|
||||
"minparams": 0,
|
||||
"permission": null,
|
||||
"requireaccount": false,
|
||||
"requireuser": false
|
||||
},
|
||||
"QUEUE": {
|
||||
"group": null,
|
||||
"hidden": false,
|
||||
"maxparams": 2,
|
||||
"minparams": 1,
|
||||
"permission": "global/queue",
|
||||
"requireaccount": true,
|
||||
"requireuser": false
|
||||
},
|
||||
"SERVER": {
|
||||
"group": null,
|
||||
"hidden": false,
|
||||
"maxparams": 2,
|
||||
"minparams": 1,
|
||||
"permission": "global/server",
|
||||
"requireaccount": true,
|
||||
"requireuser": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `anope.commands`
|
||||
|
||||
Executes the specified command.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | If non-empty then the account to execute the command as.
|
||||
1 | The service which the command exists on.
|
||||
2...n | The the command to execute and any parameters to pass to it.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified account does not exist.
|
||||
-32098 | The specified service does not exist.
|
||||
-32097 | The specified command does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
Returns an array of messages returned by the command.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
[
|
||||
"Global commands:",
|
||||
" GLOBAL Send a message to all users",
|
||||
" HELP Displays this list and give information about commands",
|
||||
" QUEUE Manages your pending message queue.",
|
||||
" SERVER Send a message to all users on a server"
|
||||
]
|
||||
```
|
||||
+1
-1
@@ -79,7 +79,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
|
||||
+11
-12
@@ -37,7 +37,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
@@ -48,11 +48,10 @@ private:
|
||||
public:
|
||||
Anope::string nick;
|
||||
Anope::string last_quit;
|
||||
Anope::string last_realname;
|
||||
/* Last usermask this nick was seen on, eg user@host */
|
||||
Anope::string last_usermask;
|
||||
/* Last uncloaked usermask, requires nickserv/auspex to see */
|
||||
Anope::string last_realhost;
|
||||
/* Last cloaked user@host this nick was seen using. */
|
||||
Anope::string last_userhost;
|
||||
/* Last real user@host this nick was seen using. */
|
||||
Anope::string last_userhost_real;
|
||||
time_t registered = Anope::CurTime;
|
||||
time_t last_seen = Anope::CurTime;
|
||||
|
||||
@@ -113,7 +112,7 @@ public:
|
||||
* @return the nick, if found
|
||||
*/
|
||||
static NickAlias *Find(const Anope::string &nick);
|
||||
static NickAlias *FindId(uint64_t id);
|
||||
static NickAlias *FindId(uint64_t uid);
|
||||
};
|
||||
|
||||
/* A registered account. Each account must have a NickAlias with the same nick as the
|
||||
@@ -129,7 +128,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
@@ -137,7 +136,7 @@ private:
|
||||
/* Channels which reference this core in some way (this is on their access list, akick list, is founder, successor, etc) */
|
||||
Serialize::Checker<std::map<ChannelInfo *, int> > chanaccess;
|
||||
/* Unique identifier for the account. */
|
||||
uint64_t id;
|
||||
uint64_t uniqueid;
|
||||
public:
|
||||
/* Name of the account. Find(display)->nc == this. */
|
||||
Anope::string display;
|
||||
@@ -151,7 +150,7 @@ public:
|
||||
/* The time this account was registered */
|
||||
time_t registered = Anope::CurTime;
|
||||
MemoInfo memos;
|
||||
std::map<Anope::string, Anope::string> last_modes;
|
||||
std::map<Anope::string, ModeData> last_modes;
|
||||
|
||||
/* Nicknames registered that are grouped to this account.
|
||||
* for n in aliases, n->nc == this.
|
||||
@@ -164,7 +163,7 @@ public:
|
||||
/* Unsaved data */
|
||||
|
||||
/** The display nick for this account. */
|
||||
NickAlias *na = nullptr;
|
||||
Serialize::Reference<NickAlias> na;
|
||||
/* Number of channels registered by this account */
|
||||
uint16_t channelcount = 0;
|
||||
/* Users online now logged into this account */
|
||||
@@ -195,7 +194,7 @@ public:
|
||||
* @return The account, if it exists
|
||||
*/
|
||||
static NickCore *Find(const Anope::string &nick);
|
||||
static NickCore *FindId(uint64_t id);
|
||||
static NickCore *FindId(uint64_t uid);
|
||||
|
||||
void AddChannelReference(ChannelInfo *ci);
|
||||
void RemoveChannelReference(ChannelInfo *ci);
|
||||
|
||||
+6
-79
@@ -14,6 +14,7 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "hashcomp.h"
|
||||
#include "utfcpp/unchecked.h"
|
||||
|
||||
namespace Anope
|
||||
{
|
||||
@@ -129,6 +130,7 @@ namespace Anope
|
||||
* Returns the string's length.
|
||||
*/
|
||||
inline size_type length() const { return this->_string.length(); }
|
||||
inline size_type utf8length() const { return utf8::unchecked::distance(str().begin(), str().end()); }
|
||||
|
||||
/**
|
||||
* Returns the size of the currently allocated storage space in the string object.
|
||||
@@ -379,11 +381,11 @@ namespace Anope
|
||||
|
||||
/** The debug level we are running at.
|
||||
*/
|
||||
extern CoreExport int Debug;
|
||||
extern CoreExport unsigned Debug;
|
||||
|
||||
/** Other command line options.
|
||||
*/
|
||||
extern CoreExport bool ReadOnly, NoFork, NoThird, NoPID, NoExpire, ProtocolDebug;
|
||||
extern CoreExport bool ReadOnly, NoFork, NoThird, NoDB, NoPID, NoExpire, ProtocolDebug;
|
||||
|
||||
/** The root of the Anope installation. Usually ~/anope
|
||||
*/
|
||||
@@ -463,33 +465,12 @@ namespace Anope
|
||||
extern CoreExport void Unhex(const string &src, string &dest);
|
||||
extern CoreExport void Unhex(const string &src, char *dest, size_t sz);
|
||||
|
||||
/** Base 64 encode a string
|
||||
* @param src The string to encode
|
||||
* @param target Where the encoded string is placed
|
||||
*/
|
||||
extern CoreExport void B64Encode(const string &src, string &target);
|
||||
|
||||
/** Base 64 decode a string
|
||||
* @param src The base64 encoded string
|
||||
* @param target The plain text result
|
||||
*/
|
||||
extern CoreExport void B64Decode(const string &src, string &target);
|
||||
|
||||
/** Encrypts what is in 'src' to 'dest'
|
||||
* @param src The source string to encrypt
|
||||
* @param dest The destination where the encrypted string is placed
|
||||
*/
|
||||
extern CoreExport bool Encrypt(const Anope::string &src, Anope::string &dest);
|
||||
|
||||
/** Returns a sequence of data formatted as the format argument specifies.
|
||||
** After the format parameter, the function expects at least as many
|
||||
** additional arguments as specified in format.
|
||||
* @param fmt Format of the Message
|
||||
* @param ... any number of parameters
|
||||
* @return a Anope::string
|
||||
*/
|
||||
extern CoreExport string printf(const char *fmt, ...) ATTR_FORMAT(1, 2);
|
||||
|
||||
/** Return the last error code
|
||||
* @return The error code
|
||||
*/
|
||||
@@ -513,9 +494,10 @@ namespace Anope
|
||||
/** Retrieves a human readable string representing the time in seconds
|
||||
* @param seconds The time on seconds, eg 60
|
||||
* @param nc The account to use language settings for to translate this string, if applicable
|
||||
* @param round Whether to round the duration to produce a shorter output.
|
||||
* @return A human readable string, eg "1 minute"
|
||||
*/
|
||||
extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = NULL);
|
||||
extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = nullptr, bool round = false);
|
||||
|
||||
/** Generates a human readable string of type "expires in ..."
|
||||
* @param expires time in seconds
|
||||
@@ -531,12 +513,6 @@ namespace Anope
|
||||
*/
|
||||
extern CoreExport Anope::string strftime(time_t t, const NickCore *nc = NULL, bool short_output = false);
|
||||
|
||||
/** Normalize buffer, stripping control characters and colors
|
||||
* @param A string to be parsed for control and color codes
|
||||
* @return A string stripped of control and color codes
|
||||
*/
|
||||
extern CoreExport Anope::string NormalizeBuffer(const Anope::string &);
|
||||
|
||||
/** Parses a raw message from the uplink and calls its command handler.
|
||||
* @param message Raw message from the uplink
|
||||
*/
|
||||
@@ -572,57 +548,8 @@ namespace Anope
|
||||
/** Generate a random number. */
|
||||
extern CoreExport int RandomNumber();
|
||||
|
||||
/** Calculates the levenshtein distance between two strings.
|
||||
* @param s1 The first string.
|
||||
* @param s2 The second string.
|
||||
*/
|
||||
extern CoreExport size_t Distance(const Anope::string &s1, const Anope::string &s2);
|
||||
|
||||
/** Update the current time. */
|
||||
extern CoreExport void UpdateTime();
|
||||
|
||||
/** Expands a path fragment that is relative to the base directory.
|
||||
* @param base The base directory that it is relative to.
|
||||
* @param fragment The fragment to expand.
|
||||
*/
|
||||
extern CoreExport Anope::string Expand(const Anope::string &base, const Anope::string &fragment);
|
||||
|
||||
/** Expands a config path. */
|
||||
inline auto ExpandConfig(const Anope::string &path) { return Expand(ConfigDir, path); }
|
||||
|
||||
/** Expands a data path. */
|
||||
inline auto ExpandData(const Anope::string &path) { return Expand(DataDir, path); }
|
||||
|
||||
/** Expands a locale path. */
|
||||
inline auto ExpandLocale(const Anope::string &path) { return Expand(LocaleDir, path); }
|
||||
|
||||
/** Expands a log path. */
|
||||
inline auto ExpandLog(const Anope::string &path) { return Expand(LogDir, path); }
|
||||
|
||||
/** Expands a module path. */
|
||||
inline auto ExpandModule(const Anope::string &path) { return Expand(ModuleDir, path); }
|
||||
|
||||
/** Formats a CTCP message for sending to a client.
|
||||
* @param name The name of the CTCP.
|
||||
* @param body If present then the body of the CTCP.
|
||||
* @return A formatted CTCP ready to send to a client.
|
||||
*/
|
||||
extern CoreExport Anope::string FormatCTCP(const Anope::string &name, const Anope::string &body = "");
|
||||
|
||||
/** Parses a CTCP message received from a client.
|
||||
* @param text The raw message to parse.
|
||||
* @param name The location to store the name of the CTCP.
|
||||
* @param body The location to store body of the CTCP if one is present.
|
||||
* @return True if the message was a well formed CTCP; otherwise, false.
|
||||
*/
|
||||
extern CoreExport bool ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body);
|
||||
|
||||
/** Replaces template variables within a string with values from a map.
|
||||
* @param str The string to template from.
|
||||
* @param vars The variables to replace within the string.
|
||||
* @return The specified string with all variables replaced within it.
|
||||
*/
|
||||
extern CoreExport Anope::string Template(const Anope::string &str, const Anope::map<Anope::string> &vars);
|
||||
}
|
||||
|
||||
/** sepstream allows for splitting token separated lists.
|
||||
|
||||
+3
-1
@@ -28,7 +28,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
time_t lastmsg;
|
||||
/* Map of actual command names -> service name/permission required */
|
||||
CommandInfo::map commands;
|
||||
/** CTCP responses this bot can send. */
|
||||
Anope::map<std::function<void(BotInfo *, User *, const Anope::string &)>> ctcps;
|
||||
/* The server-side alias used to message this bot. */
|
||||
Anope::string alias;
|
||||
/* Modes the bot should have as configured in service:modes */
|
||||
|
||||
+7
-7
@@ -36,7 +36,7 @@ class CoreExport Channel final
|
||||
static std::vector<Channel *> deleting;
|
||||
|
||||
public:
|
||||
typedef std::multimap<Anope::string, Anope::string> ModeList;
|
||||
typedef std::multimap<Anope::string, ModeData> ModeList;
|
||||
private:
|
||||
/** A map of channel modes with their parameters set on this channel
|
||||
*/
|
||||
@@ -148,10 +148,10 @@ public:
|
||||
/** Set a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The setter
|
||||
* @param cm The mode
|
||||
* @param param The param
|
||||
* @param data Data about the mode.
|
||||
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void SetModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string ¶m = "", bool enforce_mlock = true);
|
||||
void SetModeInternal(MessageSource &source, ChannelMode *cm, const ModeData &data = {}, bool enforce_mlock = true);
|
||||
|
||||
/** Remove a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The Setter
|
||||
@@ -164,19 +164,19 @@ public:
|
||||
/** Set a mode on a channel
|
||||
* @param bi The client setting the modes
|
||||
* @param cm The mode
|
||||
* @param param Optional param arg for the mode
|
||||
* @param data Data about the mode
|
||||
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m = "", bool enforce_mlock = true);
|
||||
void SetMode(BotInfo *bi, ChannelMode *cm, const ModeData &data = {}, bool enforce_mlock = true);
|
||||
|
||||
/**
|
||||
* Set a mode on a channel
|
||||
* @param bi The client setting the modes
|
||||
* @param name The mode name
|
||||
* @param param Optional param arg for the mode
|
||||
* @param data Data about the mode
|
||||
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const Anope::string ¶m = "", bool enforce_mlock = true);
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const ModeData &data = {}, bool enforce_mlock = true);
|
||||
|
||||
/** Remove a mode from a channel
|
||||
* @param bi The client setting the modes
|
||||
|
||||
+10
-8
@@ -32,10 +32,12 @@ struct CommandInfo final
|
||||
Anope::string permission;
|
||||
/* Group this command is in */
|
||||
Anope::string group;
|
||||
/* whether or not to hide this command in help output */
|
||||
/* Whether to hide this command in help and suggestions */
|
||||
bool hide = false;
|
||||
/* Only used with fantasy */
|
||||
/* Whether to prepend the channel name (only used with fantasy) */
|
||||
bool prepend_channel = false;
|
||||
/* Whether to require the FANTASY privilege (only used with fantasy) */
|
||||
bool require_privilege = true;
|
||||
};
|
||||
|
||||
/* Where the replies from commands go to. User inherits from this and is the normal
|
||||
@@ -99,9 +101,9 @@ class CoreExport Command
|
||||
Anope::string desc;
|
||||
std::vector<std::pair<Anope::string, std::function<bool(CommandSource&)>>> syntax;
|
||||
/* Allow unregistered users to use this command */
|
||||
bool allow_unregistered;
|
||||
bool allow_unregistered = false;
|
||||
/* Command requires that a user is executing it */
|
||||
bool require_user;
|
||||
bool require_user = false;
|
||||
|
||||
public:
|
||||
/* Maximum parameters accepted by this command */
|
||||
@@ -136,8 +138,8 @@ protected:
|
||||
void RequireUser(bool b);
|
||||
|
||||
public:
|
||||
bool AllowUnregistered() const;
|
||||
bool RequireUser() const;
|
||||
inline bool AllowUnregistered() const { return this->allow_unregistered; }
|
||||
inline bool RequireUser() const { return this->require_user; }
|
||||
|
||||
/** Get the command description
|
||||
* @param source The source wanting the command description
|
||||
@@ -173,9 +175,9 @@ public:
|
||||
* @param source The source of the command
|
||||
* @param message The full message to run, the command is at the beginning of the message
|
||||
*/
|
||||
static void Run(CommandSource &source, const Anope::string &message);
|
||||
static bool Run(CommandSource &source, const Anope::string &message);
|
||||
|
||||
void Run(CommandSource &source, const Anope::string &, const CommandInfo &, std::vector<Anope::string> ¶ms);
|
||||
bool Run(CommandSource &source, const Anope::string &, const CommandInfo &, std::vector<Anope::string> ¶ms);
|
||||
|
||||
/** Looks up a command name from the service name.
|
||||
* Note that if the same command exists multiple places this will return the first one encountered
|
||||
|
||||
@@ -19,6 +19,7 @@ class ChanAccess;
|
||||
class Channel;
|
||||
class ChannelInfo;
|
||||
class ChannelStatus;
|
||||
struct ModeData;
|
||||
struct ChanUserContainer;
|
||||
class ClientSocket;
|
||||
class Command;
|
||||
|
||||
+1
-7
@@ -102,7 +102,7 @@ namespace Language
|
||||
/* Commonly used language strings */
|
||||
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s\032%s\032%s\002")
|
||||
#define SERVICE_UNAVAILABLE _("Sorry, %s is temporarily unavailable.")
|
||||
#define MORE_INFO _("\002%s\002 for more information.")
|
||||
#define MORE_INFO _("Type \002%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.")
|
||||
@@ -114,7 +114,6 @@ namespace Language
|
||||
"cannot contain the space or tab characters.")
|
||||
#define PASSWORD_TOO_SHORT _("Your password is too short. It must be longer than %u characters.")
|
||||
#define PASSWORD_TOO_LONG _("Your password is too long. It must be shorter than %u characters.")
|
||||
#define NICK_NOT_REGISTERED _("Your nick isn't registered.")
|
||||
#define NICK_X_NOT_REGISTERED _("Nick \002%s\002 isn't registered.")
|
||||
#define NICK_X_NOT_IN_USE _("Nick \002%s\002 isn't currently in use.")
|
||||
#define NICK_X_NOT_ON_CHAN _("\002%s\002 is not currently on channel %s.")
|
||||
@@ -127,14 +126,9 @@ namespace Language
|
||||
#define UNKNOWN _("<unknown>")
|
||||
#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 " \
|
||||
"nick, type \002%s\032\037password\037\002. Otherwise, " \
|
||||
"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.")
|
||||
#define NICK_ALREADY_REGISTERED _("Nickname \002%s\002 is already registered!")
|
||||
#define NICK_SET_DISPLAY_CHANGED _("The new display is now \002%s\002.")
|
||||
#define NICK_CONFIRM_INVALID _("Invalid passcode has been entered, please check the email again, and retry.")
|
||||
#define CHAN_NOT_ALLOWED_TO_JOIN _("You are not permitted to be on this channel.")
|
||||
#define CHAN_X_INVALID _("Channel %s is not a valid channel.")
|
||||
#define CHAN_REACHED_CHANNEL_LIMIT _("Sorry, you have already reached your limit of \002%d\002 channels.")
|
||||
|
||||
@@ -57,35 +57,3 @@ public:
|
||||
*/
|
||||
virtual bool InvalidRange(const Anope::string &list);
|
||||
};
|
||||
|
||||
/** This class handles formatting LIST/VIEW replies.
|
||||
*/
|
||||
class CoreExport ListFormatter final
|
||||
{
|
||||
public:
|
||||
typedef std::map<Anope::string, Anope::string> ListEntry;
|
||||
private:
|
||||
NickCore *nc;
|
||||
std::vector<Anope::string> columns;
|
||||
std::vector<ListEntry> entries;
|
||||
public:
|
||||
ListFormatter(NickCore *nc);
|
||||
ListFormatter &AddColumn(const Anope::string &name);
|
||||
void AddEntry(const ListEntry &entry);
|
||||
bool IsEmpty() const;
|
||||
void Process(std::vector<Anope::string> &);
|
||||
};
|
||||
|
||||
/** This class handles formatting INFO replies
|
||||
*/
|
||||
class CoreExport InfoFormatter final
|
||||
{
|
||||
NickCore *nc;
|
||||
std::vector<std::pair<Anope::string, Anope::string> > replies;
|
||||
unsigned longest = 0;
|
||||
public:
|
||||
InfoFormatter(NickCore *nc);
|
||||
void Process(std::vector<Anope::string> &);
|
||||
Anope::string &operator[](const Anope::string &key);
|
||||
void AddOption(const Anope::string &opt);
|
||||
};
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
|
||||
+34
-14
@@ -33,6 +33,20 @@ enum ModeClass
|
||||
MC_USER
|
||||
};
|
||||
|
||||
struct ModeData final
|
||||
{
|
||||
Anope::string value;
|
||||
Anope::string set_by;
|
||||
time_t set_at;
|
||||
|
||||
ModeData(const Anope::string &v = "", const Anope::string &s = "", time_t t = 0)
|
||||
: value(v)
|
||||
, set_by(s)
|
||||
, set_at(t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** This class is the basis of all modes in Anope
|
||||
*/
|
||||
class CoreExport Mode
|
||||
@@ -56,11 +70,6 @@ public:
|
||||
*/
|
||||
Mode(const Anope::string &mname, ModeClass mclass, char mc, ModeType type);
|
||||
virtual ~Mode() = default;
|
||||
|
||||
/** Can a user set this mode, used for mlock
|
||||
* @param u The user
|
||||
*/
|
||||
virtual bool CanSet(User *u) const;
|
||||
};
|
||||
|
||||
/** This class is a user mode, all user modes use this/inherit from this
|
||||
@@ -74,6 +83,12 @@ public:
|
||||
* @param mc The mode char
|
||||
*/
|
||||
UserMode(const Anope::string &name, char mc);
|
||||
|
||||
/** Can a user set this mode, used for mlock
|
||||
* @param source The user who is setting the mode.
|
||||
* @param target The user the mode is being set on.
|
||||
*/
|
||||
virtual bool CanSet(User *source, User *target) const { return true; }
|
||||
};
|
||||
|
||||
class CoreExport UserModeParam
|
||||
@@ -108,7 +123,11 @@ public:
|
||||
*/
|
||||
ChannelMode(const Anope::string &name, char mc);
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
/** Can a user set this mode, used for mlock
|
||||
* @param u The user who is setting the mode.
|
||||
* @param c The channel the mode is being set on.
|
||||
*/
|
||||
virtual bool CanSet(User *u, Channel *c) const;
|
||||
|
||||
virtual void Check() { }
|
||||
|
||||
@@ -256,7 +275,7 @@ class CoreExport UserModeOperOnly
|
||||
public:
|
||||
UserModeOperOnly(const Anope::string &mname, char um) : UserMode(mname, um) { }
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *source, User *target) const override;
|
||||
};
|
||||
|
||||
class CoreExport UserModeNoone
|
||||
@@ -265,7 +284,7 @@ class CoreExport UserModeNoone
|
||||
public:
|
||||
UserModeNoone(const Anope::string &mname, char um) : UserMode(mname, um) { }
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *source, User *target) const override;
|
||||
};
|
||||
|
||||
/** Channel mode +k (key)
|
||||
@@ -288,7 +307,7 @@ public:
|
||||
ChannelModeOperOnly(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
|
||||
|
||||
/* Opers only */
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *u, Channel *c) const override;
|
||||
};
|
||||
|
||||
/** This class is used for channel modes only servers may set
|
||||
@@ -299,7 +318,7 @@ class CoreExport ChannelModeNoone
|
||||
public:
|
||||
ChannelModeNoone(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *u, Channel *c) const override;
|
||||
};
|
||||
|
||||
/** This is the mode manager
|
||||
@@ -311,6 +330,7 @@ public:
|
||||
class CoreExport ModeManager final
|
||||
{
|
||||
public:
|
||||
using Change = std::multimap<Mode *, std::pair<bool, ModeData>>;
|
||||
|
||||
/* Number of generic channel and user modes we are tracking */
|
||||
static unsigned GenericChannelModes;
|
||||
@@ -378,18 +398,18 @@ public:
|
||||
* @param c The channel
|
||||
* @param cm The channel mode
|
||||
* @param set true for setting, false for removing
|
||||
* @param param The param, if there is one
|
||||
* @param data Data about the mode.
|
||||
*/
|
||||
static void StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool set, const Anope::string ¶m = "");
|
||||
static void StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool set, const ModeData &data = {});
|
||||
|
||||
/** Add a mode to the stacker to be set on a user
|
||||
* @param bi The client to set the modes from
|
||||
* @param u The user
|
||||
* @param um The user mode
|
||||
* @param set true for setting, false for removing
|
||||
* @param param The param, if there is one
|
||||
* @param data Data about the mode.
|
||||
*/
|
||||
static void StackerAdd(BotInfo *bi, User *u, UserMode *um, bool set, const Anope::string ¶m = "");
|
||||
static void StackerAdd(BotInfo *bi, User *u, UserMode *um, bool set, const ModeData &data = {});
|
||||
|
||||
/** Process all of the modes in the stacker and send them to the IRCd to be set on channels/users
|
||||
*/
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "services.h"
|
||||
#include "socketengine.h"
|
||||
#include "sockets.h"
|
||||
#include "textproc.h"
|
||||
#include "threadengine.h"
|
||||
#include "timers.h"
|
||||
#include "uplink.h"
|
||||
|
||||
+9
-5
@@ -158,7 +158,9 @@ enum
|
||||
PSEUDOCLIENT = 1 << 5,
|
||||
/* Module provides IRCd protocol support */
|
||||
PROTOCOL = 1 << 6,
|
||||
MT_END = 1 << 7
|
||||
/* Module is deprecated */
|
||||
DEPRECATED = 1 << 7,
|
||||
MT_END = DEPRECATED,
|
||||
};
|
||||
typedef unsigned short ModType;
|
||||
|
||||
@@ -871,10 +873,10 @@ public:
|
||||
* @param c The channel
|
||||
* @param setter The user or server that is setting the mode
|
||||
* @param mode The mode
|
||||
* @param param The mode param, if there is one
|
||||
* @param data Data about the mode.
|
||||
* @return EVENT_STOP to make mlock/secureops etc checks not happen
|
||||
*/
|
||||
virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
|
||||
virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
|
||||
|
||||
/** Called when a mode is unset on a channel
|
||||
* @param c The channel
|
||||
@@ -1046,9 +1048,10 @@ public:
|
||||
|
||||
/** Called to determine if a channel mode can be set by a user
|
||||
* @param u The user
|
||||
* @param c The channel
|
||||
* @param cm The mode
|
||||
*/
|
||||
virtual EventReturn OnCanSet(User *u, const ChannelMode *cm) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
|
||||
virtual EventReturn OnCanSet(User *u, Channel *c, const ChannelMode *cm) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
|
||||
|
||||
virtual EventReturn OnCheckDelete(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
|
||||
|
||||
@@ -1245,9 +1248,10 @@ public:
|
||||
|
||||
/** Find the first module of a certain type
|
||||
* @param type The module type
|
||||
* @param ignoredeprecated Whether to ignore deprecated modules.
|
||||
* @return The module
|
||||
*/
|
||||
static Module *FindFirstOf(ModType type);
|
||||
static Module *FindFirstOf(ModType type, bool ignoredeprecated = false);
|
||||
|
||||
/** Checks whether this version of Anope is at least major.minor.patch.build
|
||||
* Throws a ModuleException if not
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace DNS
|
||||
{
|
||||
/** Valid query types
|
||||
@@ -29,8 +31,12 @@ namespace DNS
|
||||
QUERY_SOA = 6,
|
||||
/* Reverse DNS lookup */
|
||||
QUERY_PTR = 12,
|
||||
/* TXT lookup */
|
||||
QUERY_TXT = 16,
|
||||
/* IPv6 AAAA lookup */
|
||||
QUERY_AAAA = 28,
|
||||
/** SRV lookup */
|
||||
QUERY_SRV = 33,
|
||||
/* Zone transfer */
|
||||
QUERY_AXFR = 252,
|
||||
/* A lookup for any record */
|
||||
@@ -88,11 +94,23 @@ namespace DNS
|
||||
};
|
||||
};
|
||||
|
||||
namespace Record
|
||||
{
|
||||
struct SRV final
|
||||
{
|
||||
uint16_t priority = UINT16_MAX;
|
||||
uint16_t weight = 0;
|
||||
uint16_t port = 0;
|
||||
Anope::string host;
|
||||
};
|
||||
}
|
||||
|
||||
struct ResourceRecord final
|
||||
: Question
|
||||
{
|
||||
unsigned int ttl = 0;
|
||||
Anope::string rdata;
|
||||
std::shared_ptr<void> rdataobj;
|
||||
time_t created;
|
||||
|
||||
ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), created(Anope::CurTime) { }
|
||||
|
||||
@@ -18,6 +18,8 @@ public:
|
||||
Anope::string ident;
|
||||
Anope::string host;
|
||||
time_t time = 0;
|
||||
Anope::string validation_token;
|
||||
time_t last_validation = 0;
|
||||
|
||||
virtual ~HostRequest() = default;
|
||||
};
|
||||
|
||||
+59
-34
@@ -8,28 +8,39 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
enum HTTPError
|
||||
namespace HTTP
|
||||
{
|
||||
HTTP_ERROR_OK = 200,
|
||||
HTTP_FOUND = 302,
|
||||
HTTP_BAD_REQUEST = 400,
|
||||
HTTP_PAGE_NOT_FOUND = 404,
|
||||
HTTP_NOT_SUPPORTED = 505
|
||||
};
|
||||
struct Reply;
|
||||
struct Message;
|
||||
class Page;
|
||||
class Client;
|
||||
class Provider;
|
||||
|
||||
enum Error
|
||||
{
|
||||
OK = 200,
|
||||
FOUND = 302,
|
||||
BAD_REQUEST = 400,
|
||||
PAGE_NOT_FOUND = 404,
|
||||
NOT_SUPPORTED = 505,
|
||||
};
|
||||
}
|
||||
|
||||
/* A message to someone */
|
||||
struct HTTPReply final
|
||||
struct HTTP::Reply final
|
||||
{
|
||||
HTTPError error = HTTP_ERROR_OK;
|
||||
HTTP::Error error = HTTP::OK;
|
||||
Anope::string content_type;
|
||||
std::map<Anope::string, Anope::string, ci::less> headers;
|
||||
typedef std::list<std::pair<Anope::string, Anope::string> > cookie;
|
||||
std::vector<cookie> cookies;
|
||||
|
||||
HTTPReply() = default;
|
||||
HTTPReply &operator=(const HTTPReply &) = default;
|
||||
Reply() = default;
|
||||
Reply &operator=(const HTTP::Reply &) = default;
|
||||
|
||||
HTTPReply(const HTTPReply &other) : error(other.error), length(other.length)
|
||||
Reply(const HTTP::Reply &other)
|
||||
: error(other.error)
|
||||
, length(other.length)
|
||||
{
|
||||
content_type = other.content_type;
|
||||
headers = other.headers;
|
||||
@@ -39,7 +50,7 @@ struct HTTPReply final
|
||||
out.push_back(new Data(datum->buf, datum->len));
|
||||
}
|
||||
|
||||
~HTTPReply()
|
||||
~Reply()
|
||||
{
|
||||
for (const auto *datum : out)
|
||||
delete datum;
|
||||
@@ -81,26 +92,27 @@ struct HTTPReply final
|
||||
};
|
||||
|
||||
/* A message from someone */
|
||||
struct HTTPMessage final
|
||||
struct HTTP::Message final
|
||||
{
|
||||
std::map<Anope::string, Anope::string> headers;
|
||||
std::map<Anope::string, Anope::string> cookies;
|
||||
std::map<Anope::string, Anope::string> get_data;
|
||||
std::map<Anope::string, Anope::string> post_data;
|
||||
std::map<Anope::string, Anope::string, ci::less> headers;
|
||||
std::map<Anope::string, Anope::string, ci::less> cookies;
|
||||
std::map<Anope::string, Anope::string, ci::less> get_data;
|
||||
std::map<Anope::string, Anope::string, ci::less> post_data;
|
||||
Anope::string content;
|
||||
};
|
||||
|
||||
class HTTPClient;
|
||||
class HTTPProvider;
|
||||
|
||||
class HTTPPage
|
||||
class HTTP::Page
|
||||
: public virtual Base
|
||||
{
|
||||
Anope::string url;
|
||||
Anope::string content_type;
|
||||
|
||||
public:
|
||||
HTTPPage(const Anope::string &u, const Anope::string &ct = "text/html") : url(u), content_type(ct) { }
|
||||
Page(const Anope::string &u, const Anope::string &ct = "text/html")
|
||||
: url(u)
|
||||
, content_type(ct)
|
||||
{
|
||||
}
|
||||
|
||||
const Anope::string &GetURL() const { return this->url; }
|
||||
|
||||
@@ -113,10 +125,10 @@ public:
|
||||
* @param The HTTP header sent from the client to request the page
|
||||
* @param The HTTP header that will be sent back to the client
|
||||
*/
|
||||
virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
|
||||
virtual bool OnRequest(HTTP::Provider *, const Anope::string &, HTTP::Client *, HTTP::Message &, HTTP::Reply &) = 0;
|
||||
};
|
||||
|
||||
class HTTPClient
|
||||
class HTTP::Client
|
||||
: public ClientSocket
|
||||
, public BinarySocket
|
||||
, public Base
|
||||
@@ -128,18 +140,24 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
HTTPClient(ListenSocket *l, int f, const sockaddrs &a) : ClientSocket(l, a), BinarySocket() { }
|
||||
Client(ListenSocket *l, int f, const sockaddrs &a)
|
||||
: ClientSocket(l, a)
|
||||
, BinarySocket()
|
||||
{
|
||||
}
|
||||
|
||||
virtual const Anope::string GetIP()
|
||||
{
|
||||
return this->clientaddr.addr();
|
||||
}
|
||||
|
||||
virtual void SendError(HTTPError err, const Anope::string &msg) = 0;
|
||||
virtual void SendReply(HTTPReply *) = 0;
|
||||
virtual void SendError(HTTP::Error err, const Anope::string &msg) = 0;
|
||||
virtual void SendReply(HTTP::Reply *) = 0;
|
||||
};
|
||||
|
||||
class HTTPProvider
|
||||
#define HTTP_PROVIDER "HTTP::Provider"
|
||||
|
||||
class HTTP::Provider
|
||||
: public ListenSocket
|
||||
, public Service
|
||||
{
|
||||
@@ -150,7 +168,14 @@ public:
|
||||
std::vector<Anope::string> ext_ips;
|
||||
std::vector<Anope::string> ext_headers;
|
||||
|
||||
HTTPProvider(Module *c, const Anope::string &n, const Anope::string &i, const unsigned short p, bool s) : ListenSocket(i, p, i.find(':') != Anope::string::npos), Service(c, "HTTPProvider", n), ip(i), port(p), ssl(s) { }
|
||||
Provider(Module *c, const Anope::string &n, const Anope::string &i, const unsigned short p, bool s)
|
||||
: ListenSocket(i, p, i.find(':') != Anope::string::npos)
|
||||
, Service(c, HTTP_PROVIDER, n)
|
||||
, ip(i)
|
||||
, port(p)
|
||||
, ssl(s)
|
||||
{
|
||||
}
|
||||
|
||||
const Anope::string &GetIP() const
|
||||
{
|
||||
@@ -167,12 +192,12 @@ public:
|
||||
return this->ssl;
|
||||
}
|
||||
|
||||
virtual bool RegisterPage(HTTPPage *page) = 0;
|
||||
virtual void UnregisterPage(HTTPPage *page) = 0;
|
||||
virtual HTTPPage *FindPage(const Anope::string &name) = 0;
|
||||
virtual bool RegisterPage(HTTP::Page *page) = 0;
|
||||
virtual void UnregisterPage(HTTP::Page *page) = 0;
|
||||
virtual HTTP::Page *FindPage(const Anope::string &name) = 0;
|
||||
};
|
||||
|
||||
namespace HTTPUtils
|
||||
namespace HTTP
|
||||
{
|
||||
inline Anope::string URLDecode(const Anope::string &url)
|
||||
{
|
||||
|
||||
@@ -151,7 +151,7 @@ struct SASL::Session
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return Anope::Format("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return "A user";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -15,13 +15,6 @@ enum NewsType
|
||||
NEWS_OPER
|
||||
};
|
||||
|
||||
struct NewsMessages final
|
||||
{
|
||||
NewsType type;
|
||||
Anope::string name;
|
||||
const char *msgs[10];
|
||||
};
|
||||
|
||||
struct NewsItem
|
||||
: Serializable
|
||||
{
|
||||
|
||||
+51
-3
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "encryption.h"
|
||||
#include "httpd.h"
|
||||
|
||||
#include <variant>
|
||||
@@ -19,6 +20,7 @@ namespace RPC
|
||||
class Map;
|
||||
class Request;
|
||||
class ServiceInterface;
|
||||
struct Token;
|
||||
class Value;
|
||||
|
||||
/** Represents possible types of RPC value. */
|
||||
@@ -146,9 +148,9 @@ public:
|
||||
Anope::string name;
|
||||
Anope::string id;
|
||||
std::deque<Anope::string> data;
|
||||
HTTPReply &reply;
|
||||
HTTP::Reply &reply;
|
||||
|
||||
Request(HTTPReply &r)
|
||||
Request(HTTP::Reply &r)
|
||||
: reply(r)
|
||||
{
|
||||
}
|
||||
@@ -186,18 +188,64 @@ public:
|
||||
|
||||
const auto &GetMinParams() const { return minparams; }
|
||||
|
||||
virtual bool Run(ServiceInterface *iface, HTTPClient *client, Request &request) = 0;
|
||||
virtual bool Run(ServiceInterface *iface, HTTP::Client *client, Request &request) = 0;
|
||||
};
|
||||
|
||||
struct RPC::Token final
|
||||
{
|
||||
std::vector<Anope::string> methods;
|
||||
Anope::string token;
|
||||
Anope::string token_hash;
|
||||
};
|
||||
|
||||
class RPC::ServiceInterface
|
||||
: public Service
|
||||
{
|
||||
private:
|
||||
bool CompareToken(const RPC::Token &token, const Anope::string &rawtoken) const
|
||||
{
|
||||
if (token.token_hash.empty())
|
||||
return token.token.equals_cs(rawtoken); // Plaintext token.
|
||||
|
||||
auto *service = Service::FindService("Encryption::Provider", token.token_hash);
|
||||
if (!service)
|
||||
return false; // Malformed hash.
|
||||
|
||||
auto *hashprov = static_cast<Encryption::Provider *>(service);
|
||||
return hashprov->Compare(token.token, rawtoken);
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<Token> tokens;
|
||||
|
||||
ServiceInterface(Module *creator)
|
||||
: Service(creator, "RPC::ServiceInterface", "rpc")
|
||||
{
|
||||
}
|
||||
|
||||
bool CanExecute(const Anope::string &header, const Anope::string &method) const
|
||||
{
|
||||
if (header.compare(0, 7, "Bearer ", 7) != 0)
|
||||
return false; // No token provided.
|
||||
|
||||
auto rawtoken = Anope::B64Decode(header.substr(7));
|
||||
for (const auto &token : tokens)
|
||||
{
|
||||
if (!CompareToken(token, rawtoken))
|
||||
continue; // No valid token.
|
||||
|
||||
for (const auto &glob : token.methods)
|
||||
{
|
||||
if (glob[0] == '~' && Anope::Match(method, glob.substr(1)))
|
||||
return false; // Negative match.
|
||||
|
||||
if (Anope::Match(method, glob))
|
||||
return true; // Positive match.
|
||||
}
|
||||
}
|
||||
return false; // No match.
|
||||
}
|
||||
|
||||
virtual void Reply(Request &request) = 0;
|
||||
};
|
||||
|
||||
|
||||
+8
-12
@@ -83,7 +83,7 @@ public:
|
||||
/* Can we set vidents on users? */
|
||||
bool CanSetVIdent = false;
|
||||
|
||||
/* Can we ban specific gecos from being used? */
|
||||
/* Can we ban specific realname from being used? */
|
||||
bool CanSNLine = false;
|
||||
|
||||
/* Can we ban specific nicknames from being used? */
|
||||
@@ -131,11 +131,15 @@ public:
|
||||
/* The maximum length of a username. */
|
||||
size_t MaxUser = 0;
|
||||
|
||||
|
||||
/* Retrieves the next free UID or SID */
|
||||
virtual Anope::string UID_Retrieve();
|
||||
virtual Anope::string SID_Retrieve();
|
||||
|
||||
/** Retrieves advice on what might be the problem when a link fails.
|
||||
* @param advice The location to store the advice.
|
||||
*/
|
||||
virtual void GetLinkAdvice(std::vector<Anope::string> &advice) { }
|
||||
|
||||
/** Extracts a timestamp from a string. */
|
||||
virtual time_t ExtractTimestamp(const Anope::string &str);
|
||||
|
||||
@@ -195,19 +199,11 @@ public:
|
||||
*/
|
||||
virtual void SendSVSKill(const MessageSource &source, User *user, const Anope::string &msg);
|
||||
|
||||
virtual void SendMode(const MessageSource &source, Channel *chan, const ModeManager::Change &change);
|
||||
virtual void SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values);
|
||||
template <typename... Args>
|
||||
void SendMode(const MessageSource &source, Channel *chan, const Anope::string &modes, Args &&...args)
|
||||
{
|
||||
SendModeInternal(source, chan, modes, { Anope::ToString(args)... });
|
||||
}
|
||||
|
||||
virtual void SendMode(const MessageSource &source, User *u, const ModeManager::Change &change);
|
||||
virtual void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values);
|
||||
template <typename... Args>
|
||||
void SendMode(const MessageSource &source, User *u, const Anope::string &modes, Args &&...args)
|
||||
{
|
||||
SendModeInternal(source, u, modes, { Anope::ToString(args)... });
|
||||
}
|
||||
|
||||
/** Introduces a client to the rest of the network
|
||||
* @param u The client to introduce
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
|
||||
+17
-29
@@ -216,7 +216,7 @@ public:
|
||||
* type so you can cast it without any checks.
|
||||
* @param data The database to serialize to.
|
||||
*/
|
||||
virtual void Serialize(const Serializable *obj, Serialize::Data &data) const = 0;
|
||||
virtual void Serialize(Serializable *obj, Serialize::Data &data) const = 0;
|
||||
|
||||
/** Unserializes the specified object from the database.
|
||||
* @param obj The object to unserialize into. If the object has not been
|
||||
@@ -326,6 +326,18 @@ public:
|
||||
this->ref->DelReference(this);
|
||||
}
|
||||
|
||||
inline T *Get(bool update = true) const
|
||||
{
|
||||
if (!this->invalid)
|
||||
{
|
||||
if (this->ref && update)
|
||||
this->ref->QueueUpdate(); // This can invalidate me
|
||||
if (!this->invalid)
|
||||
return this->ref;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline Reference<T>& operator=(const Reference<T> &other)
|
||||
{
|
||||
if (this != &other)
|
||||
@@ -349,42 +361,18 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
inline operator T*() const
|
||||
inline operator T *() const
|
||||
{
|
||||
if (!this->invalid)
|
||||
{
|
||||
if (this->ref)
|
||||
// This can invalidate me
|
||||
this->ref->QueueUpdate();
|
||||
if (!this->invalid)
|
||||
return this->ref;
|
||||
}
|
||||
return NULL;
|
||||
return Get(true);
|
||||
}
|
||||
|
||||
inline T *operator*() const
|
||||
{
|
||||
if (!this->invalid)
|
||||
{
|
||||
if (this->ref)
|
||||
// This can invalidate me
|
||||
this->ref->QueueUpdate();
|
||||
if (!this->invalid)
|
||||
return this->ref;
|
||||
}
|
||||
return NULL;
|
||||
return Get(true);
|
||||
}
|
||||
|
||||
inline T *operator->() const
|
||||
{
|
||||
if (!this->invalid)
|
||||
{
|
||||
if (this->ref)
|
||||
// This can invalidate me
|
||||
this->ref->QueueUpdate();
|
||||
if (!this->invalid)
|
||||
return this->ref;
|
||||
}
|
||||
return NULL;
|
||||
return Get(true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,6 +11,93 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ANOPE_FORMAT(LAST, FORMAT, BUFFER) \
|
||||
do { \
|
||||
va_list _valist; \
|
||||
va_start(_valist, LAST); \
|
||||
(BUFFER) = Anope::Format(_valist, (FORMAT)); \
|
||||
va_end(_valist); \
|
||||
} while (false);
|
||||
|
||||
namespace Anope
|
||||
{
|
||||
/** Encode a string as base-64.
|
||||
* @param str The string to encode as base-64 .
|
||||
*/
|
||||
extern CoreExport Anope::string B64Encode(const Anope::string &str);
|
||||
|
||||
/** Decode a string from base-64.
|
||||
* @param str The string to decode from base-64.
|
||||
*/
|
||||
extern CoreExport Anope::string B64Decode(const Anope::string &str);
|
||||
|
||||
/** Calculates the levenshtein distance between two strings.
|
||||
* @param s1 The first string.
|
||||
* @param s2 The second string.
|
||||
*/
|
||||
extern CoreExport size_t Distance(const Anope::string &s1, const Anope::string &s2);
|
||||
|
||||
/** Expands a path fragment that is relative to the base directory.
|
||||
* @param base The base directory that it is relative to.
|
||||
* @param fragment The fragment to expand.
|
||||
*/
|
||||
extern CoreExport Anope::string Expand(const Anope::string &base, const Anope::string &fragment);
|
||||
|
||||
/** Expands a config path. */
|
||||
inline auto ExpandConfig(const Anope::string &path) { return Expand(ConfigDir, path); }
|
||||
|
||||
/** Expands a data path. */
|
||||
inline auto ExpandData(const Anope::string &path) { return Expand(DataDir, path); }
|
||||
|
||||
/** Expands a locale path. */
|
||||
inline auto ExpandLocale(const Anope::string &path) { return Expand(LocaleDir, path); }
|
||||
|
||||
/** Expands a log path. */
|
||||
inline auto ExpandLog(const Anope::string &path) { return Expand(LogDir, path); }
|
||||
|
||||
/** Expands a module path. */
|
||||
inline auto ExpandModule(const Anope::string &path) { return Expand(ModuleDir, path); }
|
||||
|
||||
/** Formats a string using one or more values. This uses snprintf internally but with a flexible buffer.
|
||||
* @param fmt The message to format.
|
||||
*/
|
||||
extern CoreExport Anope::string Format(const char *fmt, ...) ATTR_FORMAT(1, 2);
|
||||
|
||||
/** Formats a string using a list of values. This uses snprintf internally but with a flexible buffer.
|
||||
* @param valist A list of values to format the message with.
|
||||
* @param fmt The message to format.
|
||||
*/
|
||||
extern CoreExport Anope::string Format(va_list &valist, const char *fmt) ATTR_FORMAT(2, 0);
|
||||
|
||||
/** Formats a CTCP message for sending to a client.
|
||||
* @param name The name of the CTCP.
|
||||
* @param body If present then the body of the CTCP.
|
||||
* @return A formatted CTCP ready to send to a client.
|
||||
*/
|
||||
extern CoreExport Anope::string FormatCTCP(const Anope::string &name, const Anope::string &body = "");
|
||||
|
||||
/** Parses a CTCP message received from a client.
|
||||
* @param text The raw message to parse.
|
||||
* @param name The location to store the name of the CTCP.
|
||||
* @param body The location to store body of the CTCP if one is present.
|
||||
* @return True if the message was a well formed CTCP; otherwise, false.
|
||||
*/
|
||||
extern CoreExport bool ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body);
|
||||
|
||||
/** Remove all formatting characters from a string.
|
||||
* @param text A string containing formatting characters.
|
||||
* @return A copy of \p text with all formatting characters removed.
|
||||
*/
|
||||
extern CoreExport Anope::string RemoveFormatting(const Anope::string &text);
|
||||
|
||||
/** Replaces template variables within a string with values from a map.
|
||||
* @param str The string to template from.
|
||||
* @param vars The variables to replace within the string.
|
||||
* @return The specified string with all variables replaced within it.
|
||||
*/
|
||||
extern CoreExport Anope::string Template(const Anope::string &str, const Anope::map<Anope::string> &vars);
|
||||
}
|
||||
|
||||
class CoreExport HelpWrapper final
|
||||
{
|
||||
private:
|
||||
@@ -22,6 +109,21 @@ public:
|
||||
void SendTo(CommandSource &source);
|
||||
};
|
||||
|
||||
class CoreExport InfoFormatter final
|
||||
{
|
||||
private:
|
||||
size_t longest = 0;
|
||||
NickCore *nc;
|
||||
std::vector<Anope::string> options;
|
||||
std::vector<std::pair<Anope::string, Anope::string>> replies;
|
||||
|
||||
public:
|
||||
InfoFormatter(NickCore *nc);
|
||||
Anope::string &operator[](const Anope::string &key);
|
||||
void AddOption(const Anope::string &opt);
|
||||
void SendTo(CommandSource &source);
|
||||
};
|
||||
|
||||
class CoreExport LineWrapper final
|
||||
{
|
||||
private:
|
||||
@@ -34,3 +136,26 @@ public:
|
||||
bool GetLine(Anope::string &out);
|
||||
};
|
||||
|
||||
class CoreExport ListFormatter final
|
||||
{
|
||||
public:
|
||||
using ListEntry = std::map<Anope::string, Anope::string>;
|
||||
using FlexibleFormatFn = std::function<Anope::string(ListEntry &)>;
|
||||
|
||||
private:
|
||||
std::vector<Anope::string> columns;
|
||||
std::vector<ListEntry> entries;
|
||||
FlexibleFormatFn flexiblerow;
|
||||
NickCore *nc;
|
||||
void SendFixed(CommandSource &source);
|
||||
void SendFlexible(CommandSource &source);
|
||||
|
||||
public:
|
||||
ListFormatter(NickCore *nc);
|
||||
ListFormatter &AddColumn(const Anope::string &name);
|
||||
void AddEntry(const ListEntry &entry);
|
||||
bool IsEmpty() const;
|
||||
void SendTo(CommandSource &source);
|
||||
void SetFlexible(const Anope::string &format);
|
||||
void SetFlexible(const FlexibleFormatFn &formatter);
|
||||
};
|
||||
|
||||
+21
-11
@@ -23,8 +23,8 @@ typedef Anope::unordered_map<User *> user_map;
|
||||
|
||||
extern CoreExport user_map UserListByNick, UserListByUID;
|
||||
|
||||
extern CoreExport int OperCount;
|
||||
extern CoreExport unsigned MaxUserCount;
|
||||
extern CoreExport size_t OperCount;
|
||||
extern CoreExport size_t MaxUserCount;
|
||||
extern CoreExport time_t MaxUserTime;
|
||||
|
||||
/* Online user and channel data. */
|
||||
@@ -39,7 +39,7 @@ class CoreExport User
|
||||
static std::list<User *> quitting_users;
|
||||
|
||||
public:
|
||||
typedef std::map<Anope::string, Anope::string> ModeList;
|
||||
typedef std::map<Anope::string, ModeData> ModeList;
|
||||
protected:
|
||||
Anope::string vident;
|
||||
Anope::string ident;
|
||||
@@ -79,6 +79,10 @@ public: // XXX: exposing a tiny bit too much
|
||||
time_t timestamp;
|
||||
/* Is the user as super admin? */
|
||||
bool super_admin;
|
||||
/* The away message of the user */
|
||||
Anope::string awaymsg;
|
||||
/* The time the user went away */
|
||||
time_t awaytime = 0;
|
||||
|
||||
/* Channels the user is in */
|
||||
typedef std::map<Channel *, ChanUserContainer *> ChanUserList;
|
||||
@@ -101,7 +105,7 @@ protected:
|
||||
* @param svhost The vhost of the user
|
||||
* @param sip The ip of the user
|
||||
* @param sserver The server of the user
|
||||
* @param srealname The realname/gecos of the user
|
||||
* @param srealname The realname of the user
|
||||
* @param ts User's timestamp
|
||||
* @param smodes User's modes
|
||||
* @param suid The unique identifier of the user.
|
||||
@@ -249,9 +253,15 @@ public:
|
||||
*/
|
||||
bool HasPriv(const Anope::string &privstr);
|
||||
|
||||
/** Update the last usermask stored for a user. */
|
||||
/** Update the last mask stored for a user. */
|
||||
void UpdateHost();
|
||||
|
||||
/** Update the away state for a user. */
|
||||
void SetAway(const Anope::string &msg = "", time_t ts = 0);
|
||||
|
||||
/** Determines whether this user is away. */
|
||||
auto IsAway() const { return awaymsg.empty(); }
|
||||
|
||||
/** Check if the user has a mode
|
||||
* @param name Mode name
|
||||
* @return true or false
|
||||
@@ -261,9 +271,9 @@ public:
|
||||
/** Set a mode internally on the user, the IRCd is not informed
|
||||
* @param setter who/what is setting the mode
|
||||
* @param um The user mode
|
||||
* @param Param The param, if there is one
|
||||
* @param data Data about the mode.
|
||||
*/
|
||||
void SetModeInternal(const MessageSource &setter, UserMode *um, const Anope::string ¶m = "");
|
||||
void SetModeInternal(const MessageSource &setter, UserMode *um, const ModeData &data = {});
|
||||
|
||||
/** Remove a mode internally on the user, the IRCd is not informed
|
||||
* @param setter who/what is setting the mode
|
||||
@@ -274,16 +284,16 @@ public:
|
||||
/** Set a mode on the user
|
||||
* @param bi The client setting the mode
|
||||
* @param um The user mode
|
||||
* @param Param Optional param for the mode
|
||||
* @param data Data about the mode
|
||||
*/
|
||||
void SetMode(BotInfo *bi, UserMode *um, const Anope::string ¶m = "");
|
||||
void SetMode(BotInfo *bi, UserMode *um, const ModeData &data = {});
|
||||
|
||||
/** Set a mode on the user
|
||||
* @param bi The client setting the mode
|
||||
* @param name The mode name
|
||||
* @param Param Optional param for the mode
|
||||
* @param data Data about the mode
|
||||
*/
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const Anope::string ¶m = "");
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const ModeData &data = {});
|
||||
|
||||
/** Remove a mode on the user
|
||||
* @param bi The client setting the mode
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public:
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
|
||||
@@ -6607,7 +6607,7 @@ msgid "Service"
|
||||
msgstr "Server gefunden: %d"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr "Die Services haben den Nicknamen wieder verfügbar gemacht."
|
||||
|
||||
#, fuzzy
|
||||
|
||||
@@ -6832,7 +6832,7 @@ msgid "Service"
|
||||
msgstr "Τα services είναι ενεργά για %s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr "Οι υπηρεσίες απελευθέρωααν το ψευδώνυμό σου."
|
||||
|
||||
#, fuzzy
|
||||
|
||||
+497
-279
File diff suppressed because it is too large
Load Diff
@@ -6273,7 +6273,7 @@ msgid "Service"
|
||||
msgstr "Servicio"
|
||||
|
||||
#, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr "El nick %s retenido por los servicios ha sido liberado."
|
||||
|
||||
#, fuzzy
|
||||
|
||||
@@ -4412,7 +4412,7 @@ msgid "Last topic"
|
||||
msgstr "Dernier topic"
|
||||
|
||||
msgid "Last used"
|
||||
msgstr "Utilisé dernièrement"
|
||||
msgstr "Dernière utilisation"
|
||||
|
||||
msgid "Last usermask"
|
||||
msgstr "Dernier usermask"
|
||||
@@ -6155,7 +6155,7 @@ msgid "Service"
|
||||
msgstr "Service"
|
||||
|
||||
#, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr "La tutelle des Services sur %s a été enlevée."
|
||||
|
||||
msgid "Services Operator commands"
|
||||
|
||||
@@ -6146,7 +6146,7 @@ msgid "Service"
|
||||
msgstr "Servizio"
|
||||
|
||||
#, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr "Il blocco dei servizi sul nick %s è stato rilasciato."
|
||||
|
||||
msgid "Services Operator commands"
|
||||
|
||||
@@ -6182,7 +6182,7 @@ msgid "Service"
|
||||
msgstr "Service"
|
||||
|
||||
#, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr "Nick %s werd vrijgegeven."
|
||||
|
||||
msgid "Services Operator commands"
|
||||
|
||||
@@ -6123,7 +6123,7 @@ msgid "Service"
|
||||
msgstr "Usługa"
|
||||
|
||||
#, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr "Serwisy właśnie zwolniły nicka %s."
|
||||
|
||||
msgid "Services Operator commands"
|
||||
|
||||
@@ -5675,7 +5675,7 @@ msgid "Service"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Service's hold on %s has been released."
|
||||
msgid "Services' hold on %s has been released."
|
||||
msgstr ""
|
||||
|
||||
msgid "Services Operator commands"
|
||||
|
||||
+1627
-3622
File diff suppressed because it is too large
Load Diff
@@ -83,7 +83,7 @@ public:
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName("OP");
|
||||
char symbol = cm ? anope_dynamic_static_cast<ChannelModeStatus *>(cm)->symbol : 0;
|
||||
const auto message = Anope::printf("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
|
||||
const auto message = Anope::Format("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
|
||||
IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, message);
|
||||
}
|
||||
|
||||
@@ -196,15 +196,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (source.GetUser() && !source.GetBot() && Config->GetModule(this).Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
|
||||
{
|
||||
BotInfo *bi = c->ci->bi;
|
||||
|
||||
Entry ban("BAN", param);
|
||||
Entry ban("BAN", data.value);
|
||||
if (ban.Matches(bi))
|
||||
c->RemoveMode(bi, "BAN", param);
|
||||
c->RemoveMode(bi, "BAN", data.value);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
@@ -12,6 +12,39 @@
|
||||
#include "module.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Anope::string TypeToString(BadWordType bw)
|
||||
{
|
||||
switch (bw)
|
||||
{
|
||||
case BW_ANY:
|
||||
return "ANY";
|
||||
case BW_SINGLE:
|
||||
return "SINGLE";
|
||||
case BW_START:
|
||||
return "START";
|
||||
case BW_END:
|
||||
return "END";
|
||||
}
|
||||
return ""; // Should never happen.
|
||||
}
|
||||
|
||||
BadWordType StringToType(const Anope::string &bw)
|
||||
{
|
||||
if (bw.equals_ci("ANY") || bw.equals_ci("0"))
|
||||
return BW_ANY;
|
||||
if (bw.equals_ci("SINGLE") || bw.equals_ci("1"))
|
||||
return BW_SINGLE;
|
||||
if (bw.equals_ci("START") || bw.equals_ci("2"))
|
||||
return BW_START;
|
||||
if (bw.equals_ci("END") || bw.equals_ci("3"))
|
||||
return BW_END;
|
||||
|
||||
return BW_ANY; // Should never happen.
|
||||
}
|
||||
}
|
||||
|
||||
struct BadWordImpl final
|
||||
: BadWord
|
||||
, Serializable
|
||||
@@ -28,12 +61,12 @@ struct BadWordTypeImpl final
|
||||
{
|
||||
}
|
||||
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *bw = static_cast<const BadWordImpl *>(obj);
|
||||
data.Store("ci", bw->chan);
|
||||
data.Store("word", bw->word);
|
||||
data.Store("type", bw->type);
|
||||
data.Store("type", TypeToString(bw->type));
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &) const override;
|
||||
@@ -138,7 +171,7 @@ Serializable *BadWordTypeImpl::Unserialize(Serializable *obj, Serialize::Data &d
|
||||
if (!ci)
|
||||
return NULL;
|
||||
|
||||
unsigned int n;
|
||||
Anope::string n;
|
||||
data["type"] >> n;
|
||||
|
||||
BadWordImpl *bw;
|
||||
@@ -148,7 +181,7 @@ Serializable *BadWordTypeImpl::Unserialize(Serializable *obj, Serialize::Data &d
|
||||
bw = new BadWordImpl();
|
||||
bw->chan = sci;
|
||||
bw->word = sword;
|
||||
bw->type = static_cast<BadWordType>(n);
|
||||
bw->type = StringToType(n);
|
||||
|
||||
BadWordsImpl *bws = ci->Require<BadWordsImpl>("badwords");
|
||||
if (!obj)
|
||||
@@ -213,11 +246,12 @@ private:
|
||||
{
|
||||
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "LIST";
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
BadWords *bw = ci->GetExt<BadWords>("badwords");
|
||||
|
||||
list.AddColumn(_("Number")).AddColumn(_("Word")).AddColumn(_("Type"));
|
||||
list.SetFlexible(_("{number}: \002{word}\002 -- type: {type}"));
|
||||
|
||||
BadWords *bw = ci->GetExt<BadWords>("badwords");
|
||||
if (!bw || !bw->GetBadWordCount())
|
||||
{
|
||||
source.Reply(_("%s bad words list is empty."), ci->name.c_str());
|
||||
@@ -244,7 +278,7 @@ private:
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Number"] = Anope::ToString(Number);
|
||||
entry["Word"] = b->word;
|
||||
entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
|
||||
entry["Type"] = TypeToString(b->type);
|
||||
this->list.AddEntry(entry);
|
||||
}
|
||||
}
|
||||
@@ -263,7 +297,7 @@ private:
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Number"] = Anope::ToString(i + 1);
|
||||
entry["Word"] = b->word;
|
||||
entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
|
||||
entry["Type"] = TypeToString(b->type);
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
}
|
||||
@@ -272,14 +306,8 @@ private:
|
||||
source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Bad words list for %s:"), ci->name.c_str());
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of bad words list."));
|
||||
}
|
||||
}
|
||||
@@ -295,14 +323,7 @@ private:
|
||||
{
|
||||
Anope::string opt = word.substr(pos + 1);
|
||||
if (!opt.empty())
|
||||
{
|
||||
if (opt.equals_ci("SINGLE"))
|
||||
bwtype = BW_SINGLE;
|
||||
else if (opt.equals_ci("START"))
|
||||
bwtype = BW_START;
|
||||
else if (opt.equals_ci("END"))
|
||||
bwtype = BW_END;
|
||||
}
|
||||
bwtype = StringToType(opt);
|
||||
realword = word.substr(0, pos);
|
||||
}
|
||||
|
||||
@@ -460,15 +481,16 @@ public:
|
||||
"that starts with \037word\037. If END is specified, a kick "
|
||||
"will be done if a user says a word that ends with "
|
||||
"\037word\037. If you don't specify anything, a kick will "
|
||||
"be issued every time \037word\037 is said by a user."
|
||||
"be issued every time \037word\037 is said by a user. This "
|
||||
"will be shown in the \002LIST\002 output as ANY."
|
||||
"\n\n"
|
||||
"The \002DEL\002 command removes the given word from the "
|
||||
"bad words list. If a list of entry numbers is given, those "
|
||||
"bad words list. If a list of entry numbers is given, those "
|
||||
"entries are deleted. (See the example for LIST below.)"
|
||||
"\n\n"
|
||||
"The \002LIST\002 command displays the bad words list. If "
|
||||
"The \002LIST\002 command displays the bad words list. If "
|
||||
"a wildcard mask is given, only those entries matching the "
|
||||
"mask are displayed. If a list of entry numbers is given, "
|
||||
"mask are displayed. If a list of entry numbers is given, "
|
||||
"only those entries are shown; for example:\n"
|
||||
" \002#channel\032LIST\0322-5,7-9\002\n"
|
||||
" Lists bad words entries numbered 2 through 5 and\n"
|
||||
|
||||
@@ -41,11 +41,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
unsigned count = 0;
|
||||
ListFormatter list(source.GetAccount());
|
||||
|
||||
list.AddColumn(_("Nick")).AddColumn(_("Mask")).AddColumn(_("Real name"));
|
||||
list.SetFlexible(_("\002{nick}\002 ({mask}) [{real_name}]"));
|
||||
|
||||
unsigned count = 0;
|
||||
for (const auto &[_, bi] : *BotListByNick)
|
||||
{
|
||||
if (is_admin || !bi->oper_only)
|
||||
@@ -66,9 +66,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
source.Reply(_(
|
||||
@@ -79,10 +76,7 @@ public:
|
||||
else
|
||||
{
|
||||
source.Reply(_("Bot list:"));
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("%d bots available."), count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,15 +55,10 @@ public:
|
||||
info[_("Real name")] = bi->realname;
|
||||
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
|
||||
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
|
||||
info[_("Used on")] = Anope::printf(Language::Translate(source.nc, bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
info[_("Used on")] = Anope::Format(Language::Translate(source.nc, bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
info.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
info.SendTo(source);
|
||||
|
||||
if (source.HasPriv("botserv/administration"))
|
||||
{
|
||||
@@ -89,12 +84,7 @@ public:
|
||||
Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
info.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
info.SendTo(source);
|
||||
}
|
||||
else
|
||||
source.Reply(_("\002%s\002 is not a valid bot or registered channel."), query.c_str());
|
||||
@@ -116,7 +106,7 @@ public:
|
||||
|
||||
const Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+18
-22
@@ -1112,18 +1112,14 @@ class BSKick final
|
||||
|
||||
static void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) ATTR_FORMAT(3, 4)
|
||||
{
|
||||
va_list args;
|
||||
char buf[1024];
|
||||
|
||||
if (!ci || !ci->bi || !ci->c || !u || u->IsProtected() || !ci->c->FindUser(u))
|
||||
return;
|
||||
|
||||
Anope::string fmt = Language::Translate(u, message);
|
||||
va_start(args, message);
|
||||
vsnprintf(buf, sizeof(buf), fmt.c_str(), args);
|
||||
va_end(args);
|
||||
const auto *fmt = Language::Translate(u, message);
|
||||
|
||||
ci->c->Kick(ci->bi, u, Anope::string(buf));
|
||||
Anope::string buf;
|
||||
ANOPE_FORMAT(message, fmt, buf);
|
||||
ci->c->Kick(ci->bi, u, buf);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1157,7 +1153,7 @@ public:
|
||||
if (kd && kd->badwords)
|
||||
{
|
||||
if (kd->ttb[TTB_BADWORDS])
|
||||
info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]);
|
||||
info[_("Bad words kicker")] = Anope::Format("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]);
|
||||
else
|
||||
info[_("Bad words kicker")] = enabled;
|
||||
}
|
||||
@@ -1167,7 +1163,7 @@ public:
|
||||
if (kd && kd->bolds)
|
||||
{
|
||||
if (kd->ttb[TTB_BOLDS])
|
||||
info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]);
|
||||
info[_("Bolds kicker")] = Anope::Format("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]);
|
||||
else
|
||||
info[_("Bolds kicker")] = enabled;
|
||||
}
|
||||
@@ -1177,9 +1173,9 @@ public:
|
||||
if (kd && kd->caps)
|
||||
{
|
||||
if (kd->ttb[TTB_CAPS])
|
||||
info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent);
|
||||
info[_("Caps kicker")] = Anope::Format(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent);
|
||||
else
|
||||
info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent);
|
||||
info[_("Caps kicker")] = Anope::Format(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent);
|
||||
}
|
||||
else
|
||||
info[_("Caps kicker")] = disabled;
|
||||
@@ -1187,7 +1183,7 @@ public:
|
||||
if (kd && kd->colors)
|
||||
{
|
||||
if (kd->ttb[TTB_COLORS])
|
||||
info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]);
|
||||
info[_("Colors kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]);
|
||||
else
|
||||
info[_("Colors kicker")] = enabled;
|
||||
}
|
||||
@@ -1197,9 +1193,9 @@ public:
|
||||
if (kd && kd->flood)
|
||||
{
|
||||
if (kd->ttb[TTB_FLOOD])
|
||||
info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs);
|
||||
info[_("Flood kicker")] = Anope::Format(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs);
|
||||
else
|
||||
info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs);
|
||||
info[_("Flood kicker")] = Anope::Format(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs);
|
||||
}
|
||||
else
|
||||
info[_("Flood kicker")] = disabled;
|
||||
@@ -1207,9 +1203,9 @@ public:
|
||||
if (kd && kd->repeat)
|
||||
{
|
||||
if (kd->ttb[TTB_REPEAT])
|
||||
info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes);
|
||||
info[_("Repeat kicker")] = Anope::Format(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes);
|
||||
else
|
||||
info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), kd->repeattimes);
|
||||
info[_("Repeat kicker")] = Anope::Format(_("%s (%d times)"), enabled.c_str(), kd->repeattimes);
|
||||
}
|
||||
else
|
||||
info[_("Repeat kicker")] = disabled;
|
||||
@@ -1217,7 +1213,7 @@ public:
|
||||
if (kd && kd->reverses)
|
||||
{
|
||||
if (kd->ttb[TTB_REVERSES])
|
||||
info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]);
|
||||
info[_("Reverses kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]);
|
||||
else
|
||||
info[_("Reverses kicker")] = enabled;
|
||||
}
|
||||
@@ -1227,7 +1223,7 @@ public:
|
||||
if (kd && kd->underlines)
|
||||
{
|
||||
if (kd->ttb[TTB_UNDERLINES])
|
||||
info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]);
|
||||
info[_("Underlines kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]);
|
||||
else
|
||||
info[_("Underlines kicker")] = enabled;
|
||||
}
|
||||
@@ -1237,7 +1233,7 @@ public:
|
||||
if (kd && kd->italics)
|
||||
{
|
||||
if (kd->ttb[TTB_ITALICS])
|
||||
info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]);
|
||||
info[_("Italics kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]);
|
||||
else
|
||||
info[_("Italics kicker")] = enabled;
|
||||
}
|
||||
@@ -1247,7 +1243,7 @@ public:
|
||||
if (kd && kd->amsgs)
|
||||
{
|
||||
if (kd->ttb[TTB_AMSGS])
|
||||
info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]);
|
||||
info[_("AMSG kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]);
|
||||
else
|
||||
info[_("AMSG kicker")] = enabled;
|
||||
}
|
||||
@@ -1369,7 +1365,7 @@ public:
|
||||
BadWords *badwords = ci->GetExt<BadWords>("badwords");
|
||||
|
||||
/* Normalize the buffer */
|
||||
Anope::string nbuf = Anope::NormalizeBuffer(realbuf);
|
||||
Anope::string nbuf = Anope::RemoveFormatting(realbuf);
|
||||
bool casesensitive = Config->GetModule("botserv").Get<bool>("casesensitive");
|
||||
|
||||
/* Normalize can return an empty string if this only contains control codes etc */
|
||||
|
||||
@@ -173,7 +173,7 @@ class CommandBSSetPrivate final
|
||||
public:
|
||||
CommandBSSetPrivate(Module *creator, const Anope::string &sname = "botserv/set/private") : Command(creator, sname, 2, 2)
|
||||
{
|
||||
this->SetDesc(_("Prevent a bot from being assigned by non IRC operators"));
|
||||
this->SetDesc(_("Prevent a bot from being assigned by non Services Operators"));
|
||||
this->SetSyntax(_("\037botname\037 {\037ON|OFF\037}"));
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"This option prevents a bot from being assigned to a "
|
||||
"channel by users that aren't IRC Operators."
|
||||
"channel by users that aren't Services Operators."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
{
|
||||
std::deque<ChannelInfo *> chans;
|
||||
nc->GetChannelReferences(chans);
|
||||
int max_reg = Config->GetModule(this).Get<int>("maxregistered");
|
||||
auto max_reg = Config->GetModule(this).Get<uint16_t>("maxregistered");
|
||||
|
||||
for (auto *ci : chans)
|
||||
{
|
||||
@@ -309,7 +309,7 @@ public:
|
||||
return;
|
||||
|
||||
if (c->ci)
|
||||
c->SetMode(c->ci->WhoSends(), "REGISTERED", "", false);
|
||||
c->SetMode(c->ci->WhoSends(), "REGISTERED", {}, false);
|
||||
else
|
||||
c->RemoveMode(c->WhoSends(), "REGISTERED", "", false);
|
||||
|
||||
@@ -330,7 +330,7 @@ public:
|
||||
ci->Extend<bool>(def.upper());
|
||||
}
|
||||
|
||||
EventReturn OnCanSet(User *u, const ChannelMode *cm) override
|
||||
EventReturn OnCanSet(User *u, Channel *c, const ChannelMode *cm) override
|
||||
{
|
||||
if (Config->GetModule(this).Get<const Anope::string>("nomlock").find(cm->mchar) != Anope::string::npos
|
||||
|| Config->GetModule(this).Get<const Anope::string>("require").find(cm->mchar) != Anope::string::npos)
|
||||
@@ -461,7 +461,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (!always_lower && Anope::CurTime == c->created && c->ci && setter.GetUser() && !setter.GetUser()->server->IsULined())
|
||||
{
|
||||
@@ -470,7 +470,7 @@ public:
|
||||
if (cu && cm && !cu->status.HasMode(cm->mchar))
|
||||
{
|
||||
/* Our -o and their mode change crossing, bounce their mode */
|
||||
c->RemoveMode(c->ci->WhoSends(), mode, param);
|
||||
c->RemoveMode(c->ci->WhoSends(), mode, data.value);
|
||||
/* We don't set mlocks until after the join has finished processing, it will stack with this change,
|
||||
* so there isn't much for the user to remove except -nt etc which is likely locked anyway.
|
||||
*/
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
entry["Number"] = Anope::ToString(number);
|
||||
entry["Level"] = access->AccessSerialize();
|
||||
entry["Mask"] = access->Mask();
|
||||
entry["By"] = access->creator;
|
||||
entry["Creator"] = access->creator;
|
||||
entry["Last seen"] = timebuf;
|
||||
entry["Description"] = access->description;
|
||||
list.AddEntry(entry);
|
||||
@@ -297,7 +297,7 @@ private:
|
||||
ChannelInfo *ci;
|
||||
Command *c;
|
||||
unsigned deleted = 0;
|
||||
Anope::string Nicks;
|
||||
Anope::string nicks;
|
||||
bool denied = false;
|
||||
bool override = false;
|
||||
public:
|
||||
@@ -315,9 +315,9 @@ private:
|
||||
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << Nicks;
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << nicks;
|
||||
if (deleted == 1)
|
||||
source.Reply(_("Deleted %s from %s access list."), Nicks.c_str(), ci->name.c_str());
|
||||
source.Reply(_("Deleted %s from %s access list."), nicks.c_str(), ci->name.c_str());
|
||||
|
||||
else
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s access list.", "Deleted %d entries from %s access list."), deleted, ci->name.c_str());
|
||||
@@ -341,10 +341,9 @@ private:
|
||||
}
|
||||
|
||||
++deleted;
|
||||
if (!Nicks.empty())
|
||||
Nicks += ", " + access->Mask();
|
||||
else
|
||||
Nicks = access->Mask();
|
||||
if (!nicks.empty())
|
||||
nicks += ", ";
|
||||
nicks += access->Mask();
|
||||
|
||||
ci->EraseAccess(Number - 1);
|
||||
|
||||
@@ -436,14 +435,8 @@ private:
|
||||
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Access list for %s:"), ci->name.c_str());
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of access list"));
|
||||
}
|
||||
|
||||
@@ -460,6 +453,13 @@ private:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002 = {level}")
|
||||
: _("{number}: \002{mask}\002 = {level} ({description})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -472,7 +472,14 @@ private:
|
||||
}
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Last seen")).AddColumn(_("Description"));
|
||||
list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Last seen")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002 = {level} -- created by {creator}; last seen {last_seen}")
|
||||
: _("{number}: \002{mask}\002 = {level} -- created by {creator}; last seen {last_seen} ({description})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -569,9 +576,9 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Maintains the \002access list\002 for a channel. The access "
|
||||
"Maintains the \002access list\002 for a channel. The access "
|
||||
"list specifies which users are allowed chanop status or "
|
||||
"access to %s commands on the channel. Different "
|
||||
"access to %s commands on the channel. Different "
|
||||
"user levels allow for access to different subsets of "
|
||||
"privileges. Any registered user not on the access list has "
|
||||
"a user level of 0, and any unregistered user has a user level "
|
||||
@@ -580,7 +587,7 @@ public:
|
||||
"The \002%s\032ADD\002 command adds the given mask to the "
|
||||
"access list with the given user level; if the mask is "
|
||||
"already present on the list, its access level is changed to "
|
||||
"the level specified in the command. The \037level\037 specified "
|
||||
"the level specified in the command. The \037level\037 specified "
|
||||
"may be a numerical level or the name of a privilege (eg AUTOOP). "
|
||||
"When a user joins the channel the access they receive is from the "
|
||||
"highest level entry in the access list."
|
||||
@@ -599,14 +606,14 @@ public:
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"The \002%s\032DEL\002 command removes the given nick from the "
|
||||
"access list. If a list of entry numbers is given, those "
|
||||
"access list. If a list of entry numbers is given, those "
|
||||
"entries are deleted. (See the example for LIST below.) "
|
||||
"You may remove yourself from an access list, even if you "
|
||||
"do not have access to modify that list otherwise."
|
||||
"\n\n"
|
||||
"The \002%s\032LIST\002 command displays the access list. If "
|
||||
"The \002%s\032LIST\002 command displays the access list. If "
|
||||
"a wildcard mask is given, only those entries matching the "
|
||||
"mask are displayed. If a list of entry numbers is given, "
|
||||
"mask are displayed. If a list of entry numbers is given, "
|
||||
"only those entries are shown; for example:\n"
|
||||
" \002%s\032#channel\032LIST\0322-5,7-9\002\n"
|
||||
" Lists access entries numbered 2 through 5 and\n"
|
||||
@@ -672,7 +679,7 @@ class CommandCSLevels final
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(what);
|
||||
if (p == NULL)
|
||||
{
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s\032LEVELS\002 for a list of valid settings."),
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s\032LEVELS\002 for a list of valid settings."),
|
||||
what.c_str(), source.service->GetQueryCommand("generic/help").c_str());
|
||||
}
|
||||
else
|
||||
@@ -715,7 +722,7 @@ class CommandCSLevels final
|
||||
return;
|
||||
}
|
||||
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s\032LEVELS\002 for a list of valid settings."),
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s\032LEVELS\002 for a list of valid settings."),
|
||||
what.c_str(), source.service->GetQueryCommand("generic/help").c_str());
|
||||
}
|
||||
|
||||
@@ -725,6 +732,7 @@ class CommandCSLevels final
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Name")).AddColumn(_("Level"));
|
||||
list.SetFlexible(_("\002{name}\002 = {level}"));
|
||||
|
||||
const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
|
||||
|
||||
@@ -745,11 +753,7 @@ class CommandCSLevels final
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
|
||||
void DoReset(CommandSource &source, ChannelInfo *ci)
|
||||
@@ -826,6 +830,7 @@ public:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Name")).AddColumn(_("Description"));
|
||||
list.SetFlexible(_("\002{name}\002: {description}"));
|
||||
|
||||
for (const auto &p : PrivilegeManager::GetPrivileges())
|
||||
{
|
||||
@@ -835,11 +840,7 @@ public:
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -847,7 +848,7 @@ public:
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"The \002%s\002 command allows fine control over the meaning of "
|
||||
"the numeric access levels used for channels. With this "
|
||||
"the numeric access levels used for channels. With this "
|
||||
"command, you can define the access level required for most "
|
||||
"of %s's functions. (The \002SET\032FOUNDER\002 and this command "
|
||||
"are always restricted to the channel founder)."
|
||||
|
||||
@@ -141,7 +141,7 @@ class CommandCSAKick final
|
||||
}
|
||||
}
|
||||
|
||||
/* Match against the lastusermask of all nickalias's with equal
|
||||
/* Match against the last mask of all nickalias's with equal
|
||||
* or higher access. - Viper */
|
||||
for (const auto &[_, na2] : *NickAliasList)
|
||||
{
|
||||
@@ -150,7 +150,7 @@ class CommandCSAKick final
|
||||
AccessGroup nc_access = ci->AccessFor(na->nc), u_access = source.AccessFor(ci);
|
||||
if (na->nc && (na->nc == ci->GetFounder() || nc_access >= u_access))
|
||||
{
|
||||
Anope::string buf = na->nick + "!" + na->last_usermask;
|
||||
Anope::string buf = na->nick + "!" + na->last_userhost;
|
||||
if (Anope::Match(buf, mask))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
@@ -378,14 +378,8 @@ class CommandCSAKick final
|
||||
source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Autokick list for %s:"), ci->name.c_str());
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of autokick list"));
|
||||
}
|
||||
}
|
||||
@@ -400,6 +394,13 @@ class CommandCSAKick final
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Reason"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Reason"].empty()
|
||||
? _("{number}: \002{mask}\002")
|
||||
: _("{number}: \002{mask}\002 ({reason})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -413,6 +414,13 @@ class CommandCSAKick final
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Last used")).AddColumn(_("Reason"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Reason"].empty()
|
||||
? _("{number}: \002{mask}\002 -- added by {creator} on {created}; last used: {last_used}")
|
||||
: _("{number}: \002{mask}\002 -- added by {creator} on {created}; last used: {last_used} ({reason})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -501,13 +509,13 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Maintains the \002AutoKick list\002 for a channel. If a user "
|
||||
"Maintains the \002AutoKick list\002 for a channel. If a user "
|
||||
"on the AutoKick list attempts to join the channel, "
|
||||
"%s will ban that user from the channel, then kick "
|
||||
"the user."
|
||||
"\n\n"
|
||||
"The \002%s\032ADD\002 command adds the given nick or usermask "
|
||||
"to the AutoKick list. If a \037reason\037 is given with "
|
||||
"The \002%s\032ADD\002 command adds the given nick or mask "
|
||||
"to the AutoKick list. If a \037reason\037 is given with "
|
||||
"the command, that reason will be used when the user is "
|
||||
"kicked; if not, the default reason is \"User has been "
|
||||
"banned from the channel\". "
|
||||
@@ -516,7 +524,7 @@ public:
|
||||
"All users within that nickgroup will then be akicked. "
|
||||
"\n\n"
|
||||
"The \002%s\032DEL\002 command removes the given nick or mask "
|
||||
"from the AutoKick list. It does not, however, remove any "
|
||||
"from the AutoKick list. It does not, however, remove any "
|
||||
"bans placed by an AutoKick; those must be removed "
|
||||
"manually."
|
||||
"\n\n"
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
|
||||
static Module *me;
|
||||
|
||||
class TempBan;
|
||||
static std::vector<TempBan *> tempbans;
|
||||
|
||||
class TempBan final
|
||||
: public Timer
|
||||
{
|
||||
@@ -28,6 +31,21 @@ public:
|
||||
, mask(banmask)
|
||||
, mode(mod)
|
||||
{
|
||||
tempbans.push_back(this);
|
||||
}
|
||||
|
||||
~TempBan()
|
||||
{
|
||||
auto it = std::find(tempbans.begin(), tempbans.end(), this);
|
||||
if (it != tempbans.end())
|
||||
tempbans.erase(it);
|
||||
}
|
||||
|
||||
bool Matches(Channel *chan, ChannelMode *cmode, const Anope::string &bmask) const
|
||||
{
|
||||
return chan->name.equals_ci(this->channel)
|
||||
&& cmode->name == this->mode
|
||||
&& bmask == this->mask;
|
||||
}
|
||||
|
||||
void Tick() override
|
||||
@@ -258,10 +276,25 @@ class CSBan final
|
||||
CommandCSBan commandcsban;
|
||||
|
||||
public:
|
||||
CSBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsban(this)
|
||||
CSBan(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandcsban(this)
|
||||
{
|
||||
me = this;
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *cmode, const Anope::string ¶m) override
|
||||
{
|
||||
for (const auto *tempban : tempbans)
|
||||
{
|
||||
if (tempban->Matches(c, cmode, param))
|
||||
{
|
||||
delete tempban;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(CSBan)
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
if (!code)
|
||||
{
|
||||
code = ci->Extend<Anope::string>("channel-dropcode");
|
||||
*code = Anope::Random(Config->GetBlock("options").Get<size_t>("codelength", 15));
|
||||
*code = Anope::Random(Config->GetBlock("options").Get<size_t>("codelength", "15"));
|
||||
}
|
||||
|
||||
source.Reply(CONFIRM_DROP, ci->name.c_str(), source.service->GetQueryCommand("chanserv/drop").c_str(),
|
||||
@@ -90,14 +90,14 @@ public:
|
||||
if (source.IsServicesOper())
|
||||
{
|
||||
source.Reply(_(
|
||||
"Unregisters the specified channel. Only \002Services Operators\002 "
|
||||
"Unregisters the specified channel. Only \002Services Operators\002 "
|
||||
"can drop a channel of which they are not the founder of."
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(_(
|
||||
"Unregisters the named channel. Can only be used by "
|
||||
"Unregisters the named channel. Can only be used by "
|
||||
"the \002channel founder\002."
|
||||
));
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ struct EntryMsgTypeImpl final
|
||||
{
|
||||
}
|
||||
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *msg = static_cast<const EntryMsgImpl *>(obj);
|
||||
data.Store("ci", msg->chan);
|
||||
@@ -128,6 +128,8 @@ private:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Message"));
|
||||
list.SetFlexible(_("{number}: {message} -- created by {creator} at {created}"));
|
||||
|
||||
for (unsigned i = 0; i < (*messages)->size(); ++i)
|
||||
{
|
||||
EntryMsg *msg = (*messages)->at(i);
|
||||
@@ -140,11 +142,7 @@ private:
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of entry message list."));
|
||||
}
|
||||
|
||||
|
||||
@@ -309,8 +309,13 @@ class CommandCSFlags final
|
||||
}
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Flags")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002 = {flags} -- added by {creator} at {created}")
|
||||
: _("{number}: \002{mask}\002 = {flags} -- added by {creator} at {created} ({description})");
|
||||
});
|
||||
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i)
|
||||
@@ -348,12 +353,8 @@ class CommandCSFlags final
|
||||
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Flags list for %s"), ci->name.c_str());
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
if (count == ci->GetAccessCount())
|
||||
source.Reply(_("End of access list."));
|
||||
else
|
||||
|
||||
@@ -62,12 +62,7 @@ public:
|
||||
}
|
||||
|
||||
FOREACH_MOD(OnChanInfo, (source, ci, info, show_all));
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
info.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
info.SendTo(source);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -76,6 +76,12 @@ public:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Name")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("\002{name}\002")
|
||||
: _("\002{name}\002 ({description})");
|
||||
});
|
||||
|
||||
Anope::map<ChannelInfo *> ordered_map;
|
||||
for (const auto &[cname, ci] : *RegisteredChannelList)
|
||||
@@ -122,12 +128,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of list - %d/%d matches shown."), nchans > listmax ? listmax : nchans, nchans);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ struct LogSettingTypeImpl final
|
||||
{
|
||||
}
|
||||
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *ls = static_cast<const LogSettingImpl *>(obj);
|
||||
data.Store("ci", ls->chan);
|
||||
@@ -138,7 +138,8 @@ public:
|
||||
else
|
||||
{
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Service")).AddColumn(_("Command")).AddColumn(_("Method")).AddColumn("");
|
||||
list.AddColumn(_("Number")).AddColumn(_("Service")).AddColumn(_("Command")).AddColumn(_("Method"));
|
||||
list.SetFlexible(_("{number}: {command} on {service}: {method}"));
|
||||
|
||||
for (unsigned i = 0; i < (*ls)->size(); ++i)
|
||||
{
|
||||
@@ -147,19 +148,13 @@ public:
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Number"] = Anope::ToString(i + 1);
|
||||
entry["Service"] = log->command_service;
|
||||
entry["Command"] = !log->command_name.empty() ? log->command_name : log->service_name;
|
||||
entry["Method"] = log->method;
|
||||
entry[""] = log->extra;
|
||||
entry["Command"] = !log->command_name.empty() ? log->command_name.upper() : log->service_name;
|
||||
entry["Method"] = log->method + (log->extra.empty() ? "" : " ") + log->extra;
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
source.Reply(_("Log list for %s:"), ci->name.c_str());
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
else if (params.size() > 2)
|
||||
|
||||
@@ -39,7 +39,7 @@ struct ModeLockTypeImpl final
|
||||
: Serialize::Type("ModeLock")
|
||||
{
|
||||
}
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
@@ -211,7 +211,7 @@ struct ModeLocksImpl final
|
||||
}
|
||||
};
|
||||
|
||||
void ModeLockTypeImpl::Serialize(const Serializable *obj, Serialize::Data &data) const
|
||||
void ModeLockTypeImpl::Serialize(Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
const auto *ml = static_cast<const ModeLockImpl *>(obj);
|
||||
data.Store("ci", ml->ci);
|
||||
@@ -288,7 +288,7 @@ class CommandCSMode final
|
||||
for (auto *ml : mlocks)
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
|
||||
if (cm && cm->CanSet(source.GetUser()))
|
||||
if (cm && cm->CanSet(source.GetUser(), ci->c))
|
||||
modelocks->RemoveMLock(cm, ml->set, ml->param);
|
||||
}
|
||||
}
|
||||
@@ -320,7 +320,7 @@ class CommandCSMode final
|
||||
source.Reply(_("Unknown mode character %c ignored."), mode);
|
||||
break;
|
||||
}
|
||||
else if (u && !cm->CanSet(u))
|
||||
else if (u && !cm->CanSet(u, ci->c))
|
||||
{
|
||||
source.Reply(_("You may not (un)lock mode %c."), mode);
|
||||
break;
|
||||
@@ -412,7 +412,7 @@ class CommandCSMode final
|
||||
source.Reply(_("Unknown mode character %c ignored."), mode);
|
||||
break;
|
||||
}
|
||||
else if (u && !cm->CanSet(u))
|
||||
else if (u && !cm->CanSet(u, ci->c))
|
||||
{
|
||||
source.Reply(_("You may not (un)lock mode %c."), mode);
|
||||
break;
|
||||
@@ -450,6 +450,12 @@ class CommandCSMode final
|
||||
{
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Mode")).AddColumn(_("Param")).AddColumn(_("Creator")).AddColumn(_("Created"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Param"].empty()
|
||||
? _("{mode} -- created by {creator} on {created}")
|
||||
: _("{mode} {param} -- created by {creator} on {created}");
|
||||
});
|
||||
|
||||
for (auto *ml : mlocks)
|
||||
{
|
||||
@@ -458,7 +464,7 @@ class CommandCSMode final
|
||||
continue;
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Mode"] = Anope::printf("%c%c", ml->set ? '+' : '-', cm->mchar);
|
||||
entry["Mode"] = Anope::Format("%c%c", ml->set ? '+' : '-', cm->mchar);
|
||||
entry["Param"] = ml->param;
|
||||
entry["Creator"] = ml->setter;
|
||||
entry["Created"] = Anope::strftime(ml->created, NULL, true);
|
||||
@@ -466,12 +472,7 @@ class CommandCSMode final
|
||||
}
|
||||
|
||||
source.Reply(_("Mode locks for %s:"), ci->name.c_str());
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -508,7 +509,7 @@ class CommandCSMode final
|
||||
{
|
||||
ChannelMode *cm = ModeManager::GetChannelModes()[j];
|
||||
|
||||
if (!u || cm->CanSet(u) || can_override)
|
||||
if (!u || cm->CanSet(u, ci->c) || can_override)
|
||||
{
|
||||
if (cm->type == MODE_REGULAR || (!adding && cm->type == MODE_PARAM))
|
||||
{
|
||||
@@ -524,7 +525,7 @@ class CommandCSMode final
|
||||
if (adding == -1)
|
||||
break;
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByChar(mode);
|
||||
if (!cm || (u && !cm->CanSet(u) && !can_override))
|
||||
if (!cm || (u && !cm->CanSet(u, ci->c) && !can_override))
|
||||
continue;
|
||||
switch (cm->type)
|
||||
{
|
||||
@@ -917,9 +918,9 @@ public:
|
||||
if (!m.second.empty())
|
||||
{
|
||||
if (m.first)
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str());
|
||||
else
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str());
|
||||
}
|
||||
else
|
||||
return "";
|
||||
@@ -1008,7 +1009,7 @@ public:
|
||||
if (cm->type == MODE_REGULAR)
|
||||
{
|
||||
if (!c->HasMode(cm->name) && ml->set)
|
||||
c->SetMode(NULL, cm, "", false);
|
||||
c->SetMode(NULL, cm, {}, false);
|
||||
else if (c->HasMode(cm->name) && !ml->set)
|
||||
c->RemoveMode(NULL, cm, "", false);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Registers a channel in the %s database. In order "
|
||||
"Registers a channel in the %s database. In order "
|
||||
"to use this command, you must first be a channel operator "
|
||||
"on the channel you're trying to register. "
|
||||
"The description, which is optional, is a "
|
||||
|
||||
@@ -16,7 +16,6 @@ enum TypeInfo
|
||||
NEW, NICK_TO, NICK_FROM, JOIN, PART, QUIT, KICK
|
||||
};
|
||||
|
||||
static bool simple;
|
||||
struct SeenInfo;
|
||||
static SeenInfo *FindInfo(const Anope::string &nick);
|
||||
typedef Anope::unordered_map<SeenInfo *> database_map;
|
||||
@@ -53,12 +52,54 @@ struct SeenInfoType final
|
||||
{
|
||||
}
|
||||
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
static Anope::string TypeToString(TypeInfo ti)
|
||||
{
|
||||
switch (ti)
|
||||
{
|
||||
case NEW:
|
||||
return "NEW";
|
||||
case NICK_TO:
|
||||
return "NICK_TO";
|
||||
case NICK_FROM:
|
||||
return "NICK_FROM";
|
||||
case JOIN:
|
||||
return "JOIN";
|
||||
case PART:
|
||||
return "PART";
|
||||
case QUIT:
|
||||
return "QUIT";
|
||||
case KICK:
|
||||
return "KICK";
|
||||
}
|
||||
return ""; // Should never happen.
|
||||
}
|
||||
|
||||
static TypeInfo StringToType(const Anope::string &ti)
|
||||
{
|
||||
if (ti.equals_ci("NEW") || ti.equals_ci("0"))
|
||||
return NEW;
|
||||
if (ti.equals_ci("NICK_TO") || ti.equals_ci("1"))
|
||||
return NICK_TO;
|
||||
if (ti.equals_ci("NICK_FROM") || ti.equals_ci("2"))
|
||||
return NICK_FROM;
|
||||
if (ti.equals_ci("JOIN") || ti.equals_ci("3"))
|
||||
return JOIN;
|
||||
if (ti.equals_ci("PART") || ti.equals_ci("4"))
|
||||
return PART;
|
||||
if (ti.equals_ci("QUIT") || ti.equals_ci("5"))
|
||||
return QUIT;
|
||||
if (ti.equals_ci("KICK") || ti.equals_ci("6"))
|
||||
return KICK;
|
||||
|
||||
return NEW; // Should never happen.
|
||||
}
|
||||
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *s = static_cast<const SeenInfo *>(obj);
|
||||
data.Store("nick", s->nick);
|
||||
data.Store("vhost", s->vhost);
|
||||
data.Store("type", s->type);
|
||||
data.Store("type", TypeToString(s->type));
|
||||
data.Store("nick2", s->nick2);
|
||||
data.Store("channel", s->channel);
|
||||
data.Store("message", s->message);
|
||||
@@ -84,9 +125,9 @@ struct SeenInfoType final
|
||||
|
||||
s->nick = snick;
|
||||
data["vhost"] >> s->vhost;
|
||||
unsigned int n;
|
||||
Anope::string n;
|
||||
data["type"] >> n;
|
||||
s->type = static_cast<TypeInfo>(n);
|
||||
s->type = StringToType(n);
|
||||
data["nick2"] >> s->nick2;
|
||||
data["channel"] >> s->channel;
|
||||
data["message"] >> s->message;
|
||||
@@ -199,76 +240,6 @@ public:
|
||||
class CommandSeen final
|
||||
: public Command
|
||||
{
|
||||
static void SimpleSeen(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (!source.c || !source.c->ci)
|
||||
{
|
||||
if (source.IsOper())
|
||||
source.Reply("Seen in simple mode is designed as a fantasy command only!");
|
||||
return;
|
||||
}
|
||||
|
||||
BotInfo *bi = BotInfo::Find(params[0], true);
|
||||
if (bi)
|
||||
{
|
||||
if (bi == source.c->ci->bi)
|
||||
source.Reply(_("You found me, %s!"), source.GetNick().c_str());
|
||||
else
|
||||
source.Reply(_("%s is a network service."), bi->nick.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
NickAlias *na = NickAlias::Find(params[0]);
|
||||
if (!na)
|
||||
{
|
||||
source.Reply(_("I don't know who %s is."), params[0].c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.GetAccount() == na->nc)
|
||||
{
|
||||
source.Reply(_("Looking for yourself, eh %s?"), source.GetNick().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
User *target = User::Find(params[0], true);
|
||||
|
||||
if (target && source.c->FindUser(target))
|
||||
{
|
||||
source.Reply(_("%s is on the channel right now!"), target->nick.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &[_, uc] : source.c->users)
|
||||
{
|
||||
User *u = uc->user;
|
||||
|
||||
if (u->Account() == na->nc)
|
||||
{
|
||||
source.Reply(_("%s is on the channel right now (as %s)!"), params[0].c_str(), u->nick.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AccessGroup ag = source.c->ci->AccessFor(na->nc);
|
||||
time_t last = 0;
|
||||
for (const auto &p : ag.paths)
|
||||
{
|
||||
if (p.empty())
|
||||
continue;
|
||||
|
||||
ChanAccess *a = p[p.size() - 1];
|
||||
|
||||
if (a->GetAccount() == na->nc && a->last_seen > last)
|
||||
last = a->last_seen;
|
||||
}
|
||||
|
||||
if (last > Anope::CurTime || !last)
|
||||
source.Reply(_("I've never seen %s on this channel."), na->nick.c_str());
|
||||
else
|
||||
source.Reply(_("%s was last seen here %s ago."), na->nick.c_str(), Anope::Duration(Anope::CurTime - last, source.GetAccount()).c_str());
|
||||
}
|
||||
|
||||
public:
|
||||
CommandSeen(Module *creator) : Command(creator, "chanserv/seen", 1, 2)
|
||||
{
|
||||
@@ -281,9 +252,6 @@ public:
|
||||
{
|
||||
const Anope::string &target = params[0];
|
||||
|
||||
if (simple)
|
||||
return this->SimpleSeen(source, params);
|
||||
|
||||
if (target.length() > IRCD->MaxNick)
|
||||
{
|
||||
source.Reply(_("Nick too long, max length is %zu characters."), IRCD->MaxNick);
|
||||
@@ -314,7 +282,7 @@ public:
|
||||
if (u2)
|
||||
onlinestatus = ".";
|
||||
else
|
||||
onlinestatus = Anope::printf(Language::Translate(source.nc, _(" but %s mysteriously dematerialized.")), target.c_str());
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(" but %s mysteriously dematerialized.")), target.c_str());
|
||||
|
||||
Anope::string timebuf = Anope::Duration(Anope::CurTime - info->last, source.nc);
|
||||
Anope::string timebuf2 = Anope::strftime(info->last, source.nc, true);
|
||||
@@ -328,9 +296,9 @@ public:
|
||||
{
|
||||
u2 = User::Find(info->nick2, true);
|
||||
if (u2)
|
||||
onlinestatus = Anope::printf(Language::Translate(source.nc, _(". %s is still online.")), u2->nick.c_str());
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(". %s is still online.")), u2->nick.c_str());
|
||||
else
|
||||
onlinestatus = Anope::printf(Language::Translate(source.nc, _(", but %s mysteriously dematerialized.")), info->nick2.c_str());
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(", but %s mysteriously dematerialized.")), info->nick2.c_str());
|
||||
|
||||
source.Reply(_("%s (%s) was last seen changing nick to %s %s ago%s"),
|
||||
target.c_str(), info->vhost.c_str(), info->nick2.c_str(), timebuf.c_str(), onlinestatus.c_str());
|
||||
@@ -401,17 +369,13 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
simple = conf.GetModule(this).Get<bool>("simple");
|
||||
}
|
||||
|
||||
void OnExpireTick() override
|
||||
{
|
||||
size_t previous_size = database.size();
|
||||
time_t purgetime = Config->GetModule(this).Get<time_t>("purgetime");
|
||||
auto purgetime = Config->GetModule(this).Get<time_t>("purgetime", "90d");
|
||||
if (!purgetime)
|
||||
purgetime = Anope::DoTime("30d");
|
||||
return;
|
||||
|
||||
auto previous_size = database.size();
|
||||
for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end;)
|
||||
{
|
||||
database_map::iterator cur = it;
|
||||
@@ -461,7 +425,7 @@ public:
|
||||
private:
|
||||
static void UpdateUser(const User *u, const TypeInfo Type, const Anope::string &nick, const Anope::string &nick2, const Anope::string &channel, const Anope::string &message)
|
||||
{
|
||||
if (simple || !u->server->IsSynced())
|
||||
if (!u->server->IsSynced())
|
||||
return;
|
||||
|
||||
SeenInfo *&info = database[nick];
|
||||
|
||||
+40
-13
@@ -912,7 +912,7 @@ public:
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Enables or disables signed kicks for a "
|
||||
"channel. When \002SIGNKICK\002 is set, kicks issued with "
|
||||
"channel. When \002SIGNKICK\002 is set, kicks issued with "
|
||||
"the \002KICK\002 command will have the nick that used the "
|
||||
"command in their reason."
|
||||
"\n\n"
|
||||
@@ -1093,7 +1093,7 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Sets whether the given channel will expire. Setting this "
|
||||
"Sets whether the given channel will expire. Setting this "
|
||||
"to ON prevents the channel from expiring."
|
||||
));
|
||||
return true;
|
||||
@@ -1121,13 +1121,19 @@ class CSSet final
|
||||
|
||||
const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(s);
|
||||
Anope::string modes;
|
||||
for (const auto &[last_mode, last_value] : ci->last_modes)
|
||||
for (const auto &[last_mode, last_data] : ci->last_modes)
|
||||
{
|
||||
if (!modes.empty())
|
||||
modes += " ";
|
||||
|
||||
modes += '+';
|
||||
modes += last_mode;
|
||||
if (!last_value.empty())
|
||||
modes += "," + last_value;
|
||||
if (!last_data.value.empty())
|
||||
{
|
||||
modes += "," + Anope::ToString(last_data.set_at);
|
||||
modes += "," + last_data.set_by;
|
||||
modes += "," + last_data.value;
|
||||
}
|
||||
}
|
||||
data.Store("last_modes", modes);
|
||||
}
|
||||
@@ -1145,11 +1151,32 @@ class CSSet final
|
||||
ci->last_modes.clear();
|
||||
for (spacesepstream sep(modes); sep.GetToken(modes);)
|
||||
{
|
||||
size_t c = modes.find(',');
|
||||
if (c == Anope::string::npos)
|
||||
ci->last_modes.emplace(modes, "");
|
||||
if (modes[0] == '+')
|
||||
{
|
||||
commasepstream mode(modes, true);
|
||||
mode.GetToken(modes);
|
||||
modes.erase(0, 1);
|
||||
|
||||
ModeData info;
|
||||
Anope::string set_at;
|
||||
mode.GetToken(set_at);
|
||||
info.set_at = Anope::Convert(set_at, 0);
|
||||
mode.GetToken(info.set_by);
|
||||
info.value = mode.GetRemaining();
|
||||
|
||||
ci->last_modes.emplace(modes, info);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
ci->last_modes.emplace(modes.substr(0, c), modes.substr(c + 1));
|
||||
{
|
||||
// Begin 2.0 compatibility.
|
||||
size_t c = modes.find(',');
|
||||
if (c == Anope::string::npos)
|
||||
ci->last_modes.emplace(modes, ModeData());
|
||||
else
|
||||
ci->last_modes.emplace(modes.substr(0, c), ModeData(modes.substr(c + 1)));
|
||||
// End 2.0 compatibility.
|
||||
}
|
||||
}
|
||||
}
|
||||
} keep_modes;
|
||||
@@ -1207,8 +1234,8 @@ public:
|
||||
if (c->ci && keep_modes.HasExt(c->ci))
|
||||
{
|
||||
Channel::ModeList ml = c->ci->last_modes;
|
||||
for (const auto &[last_mode, last_value] : ml)
|
||||
c->SetMode(c->ci->WhoSends(), last_mode, last_value);
|
||||
for (const auto &[last_mode, last_data] : ml)
|
||||
c->SetMode(c->ci->WhoSends(), last_mode, last_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1230,7 +1257,7 @@ public:
|
||||
persist.Unset(ci);
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (c->ci)
|
||||
{
|
||||
@@ -1306,7 +1333,7 @@ public:
|
||||
if (persist.HasExt(ci))
|
||||
info.AddOption(_("Persistent"));
|
||||
if (noexpire.HasExt(ci))
|
||||
info.AddOption(_("No expire"));
|
||||
info.AddOption(_("No expiry"));
|
||||
if (keep_modes.HasExt(ci))
|
||||
info.AddOption(_("Keep modes"));
|
||||
if (noautoop.HasExt(ci))
|
||||
|
||||
@@ -54,7 +54,7 @@ struct CSMiscDataType
|
||||
{
|
||||
}
|
||||
|
||||
void Serialize(const Serializable *obj, Serialize::Data &sdata) const override
|
||||
void Serialize(Serializable *obj, Serialize::Data &sdata) const override
|
||||
{
|
||||
const auto *d = static_cast<const CSMiscData *>(obj);
|
||||
sdata.Store("ci", d->object);
|
||||
@@ -171,6 +171,7 @@ public:
|
||||
if (descriptions.count(source.command))
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str()));
|
||||
return true;
|
||||
}
|
||||
@@ -230,7 +231,7 @@ public:
|
||||
|
||||
void OnJoinChannel(User *user, Channel *c) override
|
||||
{
|
||||
if (!c->ci || !user->server->IsSynced() || numerics.empty())
|
||||
if (!c->ci || !user->server->IsSynced() || user->server == Me || numerics.empty())
|
||||
return;
|
||||
|
||||
for (const auto &[name, ext] : items)
|
||||
|
||||
@@ -27,7 +27,7 @@ struct CSSuspendInfoType final
|
||||
{
|
||||
}
|
||||
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
void Serialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *si = static_cast<const CSSuspendInfo *>(obj);
|
||||
data.Store("chan", si->what);
|
||||
|
||||
@@ -132,14 +132,18 @@ class CommandCSTopic final
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << (!topic.empty() ? "to change the topic to: " : "to unset the topic") << (!topic.empty() ? topic : "");
|
||||
}
|
||||
|
||||
void Append(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
void Combine(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, bool append)
|
||||
{
|
||||
const Anope::string &topic = params[2];
|
||||
|
||||
Anope::string new_topic;
|
||||
if (!ci->c->topic.empty())
|
||||
{
|
||||
new_topic = ci->c->topic + " " + topic;
|
||||
if (append)
|
||||
new_topic = ci->c->topic + " " + topic;
|
||||
else
|
||||
new_topic = topic + " " + ci->c->topic;
|
||||
|
||||
ci->last_topic.clear();
|
||||
}
|
||||
else
|
||||
@@ -155,6 +159,7 @@ public:
|
||||
this->SetDesc(_("Manipulate the topic of the specified channel"));
|
||||
this->SetSyntax(_("\037channel\037 [SET] [\037topic\037]"));
|
||||
this->SetSyntax(_("\037channel\037 APPEND \037topic\037"));
|
||||
this->SetSyntax(_("\037channel\037 PREPEND \037topic\037"));
|
||||
this->SetSyntax(_("\037channel\037 [UNLOCK|LOCK]"));
|
||||
}
|
||||
|
||||
@@ -174,7 +179,9 @@ public:
|
||||
else if (!ci->c)
|
||||
source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
|
||||
else if (subcmd.equals_ci("APPEND") && params.size() > 2)
|
||||
this->Append(source, ci, params);
|
||||
this->Combine(source, ci, params, true);
|
||||
else if (subcmd.equals_ci("PREPEND") && params.size() > 2)
|
||||
this->Combine(source, ci, params, false);
|
||||
else
|
||||
{
|
||||
Anope::string topic;
|
||||
|
||||
+15
-12
@@ -338,9 +338,8 @@ private:
|
||||
|
||||
++deleted;
|
||||
if (!nicks.empty())
|
||||
nicks += ", " + caccess->Mask();
|
||||
else
|
||||
nicks = caccess->Mask();
|
||||
nicks += ", ";
|
||||
nicks += caccess->Mask();
|
||||
|
||||
ci->EraseAccess(number - 1);
|
||||
FOREACH_MOD(OnAccessDel, (ci, source, caccess));
|
||||
@@ -398,6 +397,12 @@ private:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002")
|
||||
: _("{number}: \002{mask}\002 ({description})");
|
||||
});
|
||||
|
||||
if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos)
|
||||
{
|
||||
@@ -454,12 +459,8 @@ private:
|
||||
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("%s list for %s"), source.command.nobreak().c_str(), ci->name.c_str());
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,7 +513,7 @@ public:
|
||||
|
||||
const Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.nobreak().c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.nobreak().c_str());
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
@@ -556,16 +557,18 @@ public:
|
||||
Anope::string buf;
|
||||
for (const auto &permission : permissions[cmd])
|
||||
{
|
||||
buf += ", " + permission;
|
||||
if (!buf.empty())
|
||||
buf += ", ";
|
||||
buf += permission;
|
||||
if (buf.length() > 75)
|
||||
{
|
||||
source.Reply(" %s", buf.substr(2).c_str());
|
||||
source.Reply(" %s", buf.c_str());
|
||||
buf.clear();
|
||||
}
|
||||
}
|
||||
if (!buf.empty())
|
||||
{
|
||||
source.Reply(" %s", buf.substr(2).c_str());
|
||||
source.Reply(" %s", buf.c_str());
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
|
||||
+1
-16
@@ -181,7 +181,6 @@ class MChanstats final
|
||||
SQL::Query query;
|
||||
Anope::string SmileysHappy, SmileysSad, SmileysOther, prefix;
|
||||
std::vector<Anope::string> TableList, ProcedureList, EventList;
|
||||
bool NSDefChanstats, CSDefChanstats;
|
||||
|
||||
void RunQuery(const SQL::Query &q)
|
||||
{
|
||||
@@ -504,8 +503,6 @@ public:
|
||||
SmileysHappy = block.Get<const Anope::string>("SmileysHappy");
|
||||
SmileysSad = block.Get<const Anope::string>("SmileysSad");
|
||||
SmileysOther = block.Get<const Anope::string>("SmileysOther");
|
||||
NSDefChanstats = block.Get<bool>("ns_def_chanstats");
|
||||
CSDefChanstats = block.Get<bool>("cs_def_chanstats");
|
||||
Anope::string engine = block.Get<const Anope::string>("engine");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
|
||||
if (sql)
|
||||
@@ -540,7 +537,7 @@ public:
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
this->OnModeChange(c, setter.GetUser());
|
||||
return EVENT_CONTINUE;
|
||||
@@ -643,18 +640,6 @@ public:
|
||||
query.SetValue("channel", ci->name);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void OnChanRegistered(ChannelInfo *ci) override
|
||||
{
|
||||
if (CSDefChanstats)
|
||||
ci->Extend<bool>("CS_STATS");
|
||||
}
|
||||
|
||||
void OnNickRegister(User *user, NickAlias *na, const Anope::string &) override
|
||||
{
|
||||
if (NSDefChanstats)
|
||||
na->nc->Extend<bool>("NS_STATS");
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(MChanstats)
|
||||
|
||||
@@ -84,14 +84,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ModeData final
|
||||
struct ModeLockData final
|
||||
{
|
||||
char letter;
|
||||
Anope::string name;
|
||||
Anope::string value;
|
||||
bool set;
|
||||
|
||||
ModeData(const Anope::string &n, bool s, const Anope::string &v = "")
|
||||
ModeLockData(const Anope::string &n, bool s, const Anope::string &v = "")
|
||||
: letter(0)
|
||||
, name(n)
|
||||
, value(v)
|
||||
@@ -99,7 +99,7 @@ struct ModeData final
|
||||
{
|
||||
}
|
||||
|
||||
ModeData(char l, const Anope::string &v = "")
|
||||
ModeLockData(char l, const Anope::string &v = "")
|
||||
: letter(l)
|
||||
, value(v)
|
||||
, set(true)
|
||||
@@ -123,7 +123,7 @@ struct ChannelData final
|
||||
Anope::string info_adder;
|
||||
Anope::string info_message;
|
||||
time_t info_ts = 0;
|
||||
std::vector<ModeData> mlocks;
|
||||
std::vector<ModeLockData> mlocks;
|
||||
Anope::string suspend_by;
|
||||
Anope::string suspend_reason;
|
||||
time_t suspend_ts = 0;
|
||||
@@ -134,9 +134,9 @@ struct UserData final
|
||||
Anope::string info_adder;
|
||||
Anope::string info_message;
|
||||
time_t info_ts = 0;
|
||||
Anope::string last_mask;
|
||||
Anope::string last_quit;
|
||||
Anope::string last_real_mask;
|
||||
Anope::string last_userhost;
|
||||
Anope::string last_userhost_real;
|
||||
bool noexpire = false;
|
||||
bool protect = false;
|
||||
std::optional<time_t> protectafter;
|
||||
@@ -286,22 +286,7 @@ private:
|
||||
data->mlocks.emplace_back("REGISTERED", set);
|
||||
|
||||
// Atheme also supports per-ircd values here (ew).
|
||||
if (IRCD->owner->name == "bahamut")
|
||||
{
|
||||
if (locks & 0x1000u)
|
||||
data->mlocks.emplace_back("BLOCKCOLOR", set);
|
||||
if (locks & 0x2000u)
|
||||
data->mlocks.emplace_back("REGMODERATED", set);
|
||||
if (locks & 0x4000u)
|
||||
data->mlocks.emplace_back("REGISTEREDONLY", set);
|
||||
if (locks & 0x8000u)
|
||||
data->mlocks.emplace_back("OPERONLY", set);
|
||||
|
||||
// Anope doesn't recognise the following Bahamut modes currently:
|
||||
// - 0x10000u ('A')
|
||||
// - 0x20000u ('P')
|
||||
}
|
||||
else if (IRCD->owner->name == "inspircd")
|
||||
if (IRCD->owner->name == "inspircd")
|
||||
{
|
||||
if (locks & 0x1000u)
|
||||
data->mlocks.emplace_back("BLOCKCOLOR", set);
|
||||
@@ -447,7 +432,7 @@ private:
|
||||
// crypt3-md5 Converted to enc_posix
|
||||
// crypt3-sha2-256 Converted to enc_posix
|
||||
// crypt3-sha2-512 Converted to enc_posix
|
||||
// ircservices Converted to enc_old
|
||||
// ircservices NO
|
||||
// pbkdf2 NO
|
||||
// pbkdf2v2 NO
|
||||
// rawmd5 Converted to enc_md5
|
||||
@@ -458,10 +443,9 @@ private:
|
||||
if (pass.compare(0, 18, "$anope$enc_sha256$", 18) == 0)
|
||||
{
|
||||
auto sep = pass.find('$', 18);
|
||||
Anope::string iv, pass;
|
||||
Anope::B64Decode(pass.substr(18, sep - 18), iv);
|
||||
Anope::B64Decode(pass.substr(sep + 1), pass);
|
||||
nc->pass = "sha256:" + Anope::Hex(pass) + ":" + Anope::Hex(iv);
|
||||
auto iv = Anope::B64Decode(pass.substr(18, sep - 18));
|
||||
auto pw = Anope::B64Decode(pass.substr(sep + 1));
|
||||
nc->pass = "sha256:" + Anope::Hex(pw) + ":" + Anope::Hex(iv);
|
||||
}
|
||||
|
||||
else if (pass.compare(0, 9, "$argon2d$", 9) == 0)
|
||||
@@ -475,14 +459,10 @@ private:
|
||||
|
||||
else if (pass.compare(0, 8, "$base64$", 8) == 0)
|
||||
{
|
||||
Anope::string rawpass;
|
||||
Anope::B64Decode(pass.substr(8), rawpass);
|
||||
auto rawpass = Anope::B64Decode(pass.substr(8));
|
||||
Anope::Encrypt(rawpass, nc->pass);
|
||||
}
|
||||
|
||||
else if (pass.compare(0, 13, "$ircservices$", 13) == 0)
|
||||
nc->pass = "oldmd5:" + pass.substr(13);
|
||||
|
||||
else if (pass.compare(0, 8, "$rawmd5$", 8) == 0)
|
||||
nc->pass = "md5:" + pass.substr(8);
|
||||
|
||||
@@ -527,7 +507,7 @@ private:
|
||||
|
||||
if (!forbid_service)
|
||||
{
|
||||
Log(this) << "Unable to convert forbidden email " << email << " as os_forbid is not loaded";
|
||||
Log(this) << "Unable to convert forbidden email address " << email << " as os_forbid is not loaded";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -640,6 +620,7 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
auto originalflags = flags;
|
||||
Anope::string accessflags;
|
||||
ApplyAccess(flags, 'A', accessflags, { "ACCESS_LIST" });
|
||||
ApplyAccess(flags, 'a', accessflags, { "AUTOPROTECT", "PROTECT", "PROTECTME" });
|
||||
@@ -662,7 +643,7 @@ private:
|
||||
auto *access = accessprov->Create();
|
||||
access->SetMask(mask, ci);
|
||||
access->creator = setter;
|
||||
access->description = "Imported from Atheme";
|
||||
access->description = "Imported from Atheme: " + flags;
|
||||
access->last_seen = modifiedtime;
|
||||
access->created = modifiedtime;
|
||||
access->AccessUnserialize(accessflags);
|
||||
@@ -820,7 +801,7 @@ private:
|
||||
|
||||
auto *ni = news_service->CreateNewsItem();
|
||||
ni->type = NEWS_LOGON;
|
||||
ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->text = Anope::Format("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->who = setter;
|
||||
ni->time = ts;
|
||||
news_service->AddNewsItem(ni);
|
||||
@@ -846,7 +827,7 @@ private:
|
||||
|
||||
auto *ni = news_service->CreateNewsItem();
|
||||
ni->type = NEWS_OPER;
|
||||
ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->text = Anope::Format("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->who = setter;
|
||||
ni->time = ts;
|
||||
news_service->AddNewsItem(ni);
|
||||
@@ -1160,9 +1141,9 @@ private:
|
||||
else if (key == "private:freeze:timestamp")
|
||||
data->suspend_ts = Anope::Convert<time_t>(value, 0);
|
||||
else if (key == "private:host:actual")
|
||||
data->last_real_mask = value;
|
||||
data->last_userhost_real = value;
|
||||
else if (key == "private:host:vhost")
|
||||
data->last_mask = value;
|
||||
data->last_userhost = value;
|
||||
else if (key == "private:lastquit:message")
|
||||
data->last_quit = value;
|
||||
else if (key == "private:loginfail:failnum")
|
||||
@@ -1328,14 +1309,14 @@ private:
|
||||
auto *data = userdata.Get(nc);
|
||||
if (data)
|
||||
{
|
||||
if (!data->last_mask.empty())
|
||||
na->last_usermask = data->last_mask;
|
||||
if (!data->last_userhost.empty())
|
||||
na->last_userhost = data->last_userhost;
|
||||
|
||||
if (!data->last_quit.empty())
|
||||
na->last_quit = data->last_quit;
|
||||
|
||||
if (!data->last_real_mask.empty())
|
||||
na->last_realhost = data->last_real_mask;
|
||||
if (!data->last_userhost_real.empty())
|
||||
na->last_userhost_real = data->last_userhost_real;
|
||||
|
||||
if (data->noexpire)
|
||||
na->Extend<bool>("NS_NO_EXPIRE");
|
||||
|
||||
@@ -11,31 +11,6 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
class SaveData final
|
||||
: public Serialize::Data
|
||||
{
|
||||
public:
|
||||
Anope::string last;
|
||||
std::fstream *fs = nullptr;
|
||||
|
||||
std::iostream &operator[](const Anope::string &key) override
|
||||
{
|
||||
if (key != last)
|
||||
{
|
||||
*fs << "\nDATA " << key << " ";
|
||||
last = key;
|
||||
}
|
||||
|
||||
return *fs;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadData final
|
||||
: public Serialize::Data
|
||||
{
|
||||
@@ -97,133 +72,14 @@ public:
|
||||
|
||||
class DBFlatFile final
|
||||
: public Module
|
||||
, public Pipe
|
||||
{
|
||||
/* Day the last backup was on */
|
||||
int last_day = 0;
|
||||
private:
|
||||
bool loaded = false;
|
||||
|
||||
int child_pid = -1;
|
||||
|
||||
void BackupDatabase()
|
||||
{
|
||||
tm *tm = localtime(&Anope::CurTime);
|
||||
|
||||
if (tm->tm_mday != last_day)
|
||||
{
|
||||
last_day = tm->tm_mday;
|
||||
|
||||
std::set<Anope::string> dbs;
|
||||
dbs.insert(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
for (const auto &type_order : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
Serialize::Type *stype = Serialize::Type::Find(type_order);
|
||||
|
||||
if (stype && stype->GetOwner())
|
||||
dbs.insert("module_" + stype->GetOwner()->name + ".db");
|
||||
}
|
||||
|
||||
const auto backupdir = Anope::ExpandData("backups");
|
||||
for (const auto &db : dbs)
|
||||
{
|
||||
const auto oldname = Anope::ExpandData(db);
|
||||
const auto basename = Anope::Expand(backupdir, db + "-");
|
||||
const auto newname = Anope::printf("%s%04i-%02i-%02i", basename.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
|
||||
/* Backup already exists or no database to backup */
|
||||
if (Anope::IsFile(newname) || !Anope::IsFile(oldname))
|
||||
continue;
|
||||
|
||||
Log(LOG_DEBUG) << "db_flatfile: Attempting to rename " << db << " to " << newname;
|
||||
if (rename(oldname.c_str(), newname.c_str()))
|
||||
{
|
||||
Anope::string err = Anope::LastError();
|
||||
Log(this) << "Unable to back up database " << db << " (" << err << ")!";
|
||||
|
||||
if (!Config->GetModule(this).Get<bool>("nobackupokay"))
|
||||
{
|
||||
Anope::Quitting = true;
|
||||
Anope::QuitReason = "Unable to back up database " + db + " (" + err + ")";
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto keepbackups = Config->GetModule(this).Get<unsigned>("keepbackups", "7");
|
||||
if (!keepbackups)
|
||||
continue;
|
||||
|
||||
std::error_code ec;
|
||||
std::set<Anope::string> old_backups;
|
||||
for (const auto &entry : std::filesystem::directory_iterator(backupdir.str(), ec))
|
||||
{
|
||||
Anope::string entryname = entry.path().string();
|
||||
if (entryname.compare(0, basename.length(), basename) != 0)
|
||||
continue;
|
||||
|
||||
old_backups.insert(entryname);
|
||||
if (old_backups.size() <= keepbackups)
|
||||
continue;
|
||||
|
||||
Log(LOG_DEBUG) << "Deleting expired backup " << *old_backups.begin();
|
||||
if (!std::filesystem::remove(old_backups.begin()->str(), ec))
|
||||
{
|
||||
Log(this) << "Failed to delete expired backup " << *old_backups.begin() << ": " << ec.message();
|
||||
continue;
|
||||
}
|
||||
old_backups.erase(old_backups.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
|
||||
DBFlatFile(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, DATABASE | DEPRECATED | VENDOR)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void OnRestart() override
|
||||
{
|
||||
OnShutdown();
|
||||
}
|
||||
|
||||
void OnShutdown() override
|
||||
{
|
||||
if (child_pid > -1)
|
||||
{
|
||||
Log(this) << "Waiting for child to exit...";
|
||||
|
||||
int status;
|
||||
waitpid(child_pid, &status, 0);
|
||||
|
||||
Log(this) << "Done";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnNotify() override
|
||||
{
|
||||
char buf[512];
|
||||
int i = this->Read(buf, sizeof(buf) - 1);
|
||||
if (i <= 0)
|
||||
return;
|
||||
buf[i] = 0;
|
||||
|
||||
child_pid = -1;
|
||||
|
||||
if (!*buf)
|
||||
{
|
||||
Log(this) << "Finished saving databases";
|
||||
return;
|
||||
}
|
||||
|
||||
Log(this) << "Error saving databases: " << buf;
|
||||
|
||||
if (!Config->GetModule(this).Get<bool>("nobackupokay"))
|
||||
Anope::Quitting = true;
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase() override
|
||||
@@ -270,110 +126,6 @@ public:
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
|
||||
void OnSaveDatabase() override
|
||||
{
|
||||
if (child_pid > -1)
|
||||
{
|
||||
Log(this) << "Database save is already in progress!";
|
||||
return;
|
||||
}
|
||||
|
||||
BackupDatabase();
|
||||
|
||||
int i = -1;
|
||||
#ifndef _WIN32
|
||||
if (!Anope::Quitting && Config->GetModule(this).Get<bool>("fork"))
|
||||
{
|
||||
i = fork();
|
||||
if (i > 0)
|
||||
{
|
||||
child_pid = i;
|
||||
return;
|
||||
}
|
||||
else if (i < 0)
|
||||
Log(this) << "Unable to fork for database save";
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
std::map<Module *, std::fstream *> databases;
|
||||
|
||||
/* First open the databases of all of the registered types. This way, if we have a type with 0 objects, that database will be properly cleared */
|
||||
for (const auto &[_, s_type] : Serialize::Type::GetTypes())
|
||||
{
|
||||
if (databases[s_type->GetOwner()])
|
||||
continue;
|
||||
|
||||
Anope::string db_name;
|
||||
if (s_type->GetOwner())
|
||||
db_name = Anope::ExpandData("module_" + s_type->GetOwner()->name + ".db");
|
||||
else
|
||||
db_name = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream((db_name + ".tmp").c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
|
||||
|
||||
if (!fs->is_open())
|
||||
Log(this) << "Unable to open " << db_name << " for writing";
|
||||
}
|
||||
|
||||
SaveData data;
|
||||
const std::list<Serializable *> &items = Serializable::GetItems();
|
||||
for (auto *base : items)
|
||||
{
|
||||
Serialize::Type *s_type = base->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
data.fs = databases[s_type->GetOwner()];
|
||||
if (!data.fs || !data.fs->is_open())
|
||||
continue;
|
||||
|
||||
*data.fs << "OBJECT " << s_type->GetName();
|
||||
if (base->id)
|
||||
*data.fs << "\nID " << base->id;
|
||||
s_type->Serialize(base, data);
|
||||
*data.fs << "\nEND\n";
|
||||
}
|
||||
|
||||
for (auto &[mod, f] : databases)
|
||||
{
|
||||
const auto db_name = Anope::ExpandData((mod ? (mod->name + ".db") : Config->GetModule(this).Get<const Anope::string>("database", "anope.db")));
|
||||
|
||||
if (!f->is_open() || !f->good())
|
||||
{
|
||||
this->Write("Unable to write database " + db_name);
|
||||
|
||||
f->close();
|
||||
}
|
||||
else
|
||||
{
|
||||
f->close();
|
||||
#ifdef _WIN32
|
||||
/* Windows rename() fails if the file already exists. */
|
||||
remove(db_name.c_str());
|
||||
#endif
|
||||
rename((db_name + ".tmp").c_str(), db_name.c_str());
|
||||
}
|
||||
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (i)
|
||||
throw;
|
||||
}
|
||||
|
||||
if (!i)
|
||||
{
|
||||
this->Notify();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load just one type. Done if a module is reloaded during runtime */
|
||||
void OnSerializeTypeCreate(Serialize::Type *stype) override
|
||||
{
|
||||
if (!loaded)
|
||||
|
||||
+189
-159
@@ -20,23 +20,13 @@ namespace fs = std::filesystem;
|
||||
|
||||
// TODO:
|
||||
// * forking into background
|
||||
// * stable key order
|
||||
|
||||
inline Anope::string yyjson_mut_get_astr(yyjson_mut_val *val)
|
||||
inline Anope::string yyjson_get_astr(yyjson_val *val)
|
||||
{
|
||||
const auto *str = yyjson_mut_get_str(val);
|
||||
const auto *str = yyjson_get_str(val);
|
||||
return str ? str : "";
|
||||
}
|
||||
|
||||
inline void yyjson_mut_obj_upsert(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, yyjson_mut_val *val)
|
||||
{
|
||||
auto *oldval = yyjson_mut_obj_get(obj, key);
|
||||
if (oldval)
|
||||
yyjson_mut_obj_replace(obj, yyjson_mut_str(doc, key), val);
|
||||
else
|
||||
yyjson_mut_obj_add_val(doc, obj, key, val);
|
||||
}
|
||||
|
||||
class Data final
|
||||
: public Serialize::Data
|
||||
{
|
||||
@@ -48,37 +38,42 @@ public:
|
||||
Anope::map<std::stringstream> data;
|
||||
|
||||
// Used when writing data.
|
||||
Data() = default;
|
||||
Data(Serialize::Type *s_type, Serializable *obj)
|
||||
{
|
||||
if (obj->id)
|
||||
this->id = obj->id;
|
||||
s_type->Serialize(obj, *this);
|
||||
}
|
||||
|
||||
// Used when reading data.
|
||||
Data(yyjson_mut_val *elem)
|
||||
Data(yyjson_val *elem)
|
||||
{
|
||||
size_t idx, max;
|
||||
yyjson_mut_val *key, *value;
|
||||
yyjson_mut_obj_foreach(elem, idx, max, key, value)
|
||||
yyjson_val *key, *value;
|
||||
yyjson_obj_foreach(elem, idx, max, key, value)
|
||||
{
|
||||
if (yyjson_mut_get_type(key) != YYJSON_TYPE_STR)
|
||||
if (yyjson_get_type(key) != YYJSON_TYPE_STR)
|
||||
continue;
|
||||
|
||||
Anope::string akey(yyjson_mut_get_str(key));
|
||||
if (akey.equals_ci("id"))
|
||||
auto akey = yyjson_get_astr(key);
|
||||
if (akey.equals_ci("@id"))
|
||||
{
|
||||
this->id = yyjson_mut_get_uint(value);
|
||||
this->id = yyjson_get_uint(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (yyjson_mut_is_bool(value))
|
||||
data[akey] << yyjson_mut_get_bool(value);
|
||||
else if (yyjson_mut_is_int(value))
|
||||
data[akey] << yyjson_mut_get_int(value);
|
||||
else if (yyjson_mut_is_null(value))
|
||||
if (yyjson_is_bool(value))
|
||||
data[akey] << yyjson_get_bool(value);
|
||||
else if (yyjson_is_int(value))
|
||||
data[akey] << yyjson_get_int(value);
|
||||
else if (yyjson_is_null(value))
|
||||
data[akey];
|
||||
else if (yyjson_mut_is_real(value))
|
||||
data[akey] << yyjson_mut_get_real(value);
|
||||
else if (yyjson_mut_is_str(value))
|
||||
data[akey] << yyjson_mut_get_str(value);
|
||||
else if (yyjson_mut_is_uint(value))
|
||||
data[akey] << yyjson_mut_get_uint(value);
|
||||
else if (yyjson_is_real(value))
|
||||
data[akey] << yyjson_get_real(value);
|
||||
else if (yyjson_is_str(value))
|
||||
data[akey] << yyjson_get_astr(value);
|
||||
else if (yyjson_is_uint(value))
|
||||
data[akey] << yyjson_get_uint(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,16 +81,29 @@ public:
|
||||
{
|
||||
return data[key];
|
||||
}
|
||||
|
||||
size_t Hash() const override
|
||||
{
|
||||
size_t hash = 0;
|
||||
for (const auto &[_, value] : this->data)
|
||||
{
|
||||
auto valuestr = value.str();
|
||||
if (!valuestr.empty())
|
||||
hash ^= Anope::hash_cs()(valuestr);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
class DBJSON final
|
||||
: public Module
|
||||
{
|
||||
private:
|
||||
using DBPair = std::pair<yyjson_mut_doc *, yyjson_mut_val *>;
|
||||
// Multimap from serializable type to serializable data.
|
||||
using DBData = Anope::multimap<Data>;
|
||||
|
||||
// The databases which have already been loaded from disk.
|
||||
std::unordered_map<Module *, DBPair> databases;
|
||||
std::unordered_map<Module *, DBData> databases;
|
||||
|
||||
// Whether OnLoadDatabase has been called yet.
|
||||
bool loaded = false;
|
||||
@@ -182,7 +190,7 @@ private:
|
||||
return; // No backups.
|
||||
|
||||
auto backupdir = Anope::ExpandData(modconf.Get<Anope::string>("backup_directory", "backups"));
|
||||
if (!fs::is_directory(backupdir.str(), ec) && !ec)
|
||||
if (!fs::is_directory(backupdir.str(), ec))
|
||||
{
|
||||
fs::create_directories(backupdir.str(), ec);
|
||||
if (ec)
|
||||
@@ -201,55 +209,131 @@ private:
|
||||
CreateBackup(backupdir, dbpath, monthly_backups, "%Y-%m", "\?\?\?\?-\?\?");
|
||||
}
|
||||
|
||||
DBPair ReadDatabase(const Anope::string &dbname)
|
||||
void LoadType(Serialize::Type *s_type, DBData &data)
|
||||
{
|
||||
auto entries = data.equal_range(s_type->GetName());
|
||||
if (entries.first == entries.second)
|
||||
return;
|
||||
|
||||
for (auto it = entries.first; it != entries.second; ++it)
|
||||
s_type->Unserialize(nullptr, it->second);
|
||||
}
|
||||
|
||||
std::optional<DBData> ReadDatabase(const Anope::string &dbname)
|
||||
{
|
||||
yyjson_read_err errmsg;
|
||||
const auto flags = YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INVALID_UNICODE;
|
||||
auto *idoc = yyjson_read_file(dbname.c_str(), flags, nullptr, &errmsg);
|
||||
if (!idoc)
|
||||
auto *doc = yyjson_read_file(dbname.c_str(), flags, nullptr, &errmsg);
|
||||
if (!doc)
|
||||
{
|
||||
Log(this) << "Unable to read " << dbname << ": error #" << errmsg.code << ": " << errmsg.msg;
|
||||
return { nullptr, nullptr };
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// We operate on a mutable document because we need to write to it later.
|
||||
auto *doc = yyjson_doc_mut_copy(idoc, nullptr);
|
||||
yyjson_doc_free(idoc);
|
||||
|
||||
auto *root = yyjson_mut_doc_get_root(doc);
|
||||
if (!yyjson_mut_is_obj(root))
|
||||
auto *root = yyjson_doc_get_root(doc);
|
||||
if (!yyjson_is_obj(root))
|
||||
{
|
||||
Log(this) << "Unable to read " << dbname << ": root element is not an object";
|
||||
return { nullptr, nullptr };
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto version = yyjson_mut_get_uint(yyjson_mut_obj_get(root, "version"));
|
||||
auto version = yyjson_get_uint(yyjson_obj_get(root, "version"));
|
||||
if (version && version != ANOPE_DATABASE_VERSION)
|
||||
{
|
||||
Log(this) << "Refusing to load an unsupported database version: " << version;
|
||||
return { nullptr, nullptr };
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto generator = yyjson_mut_get_astr(yyjson_mut_obj_get(root, "generator"));
|
||||
auto updated = yyjson_mut_get_uint(yyjson_mut_obj_get(root, "updated"));
|
||||
auto generator = yyjson_get_astr(yyjson_obj_get(root, "generator"));
|
||||
auto updated = yyjson_get_uint(yyjson_obj_get(root, "updated"));
|
||||
Log(LOG_DEBUG) << "Database " << dbname << " was generated on " << Anope::strftime(updated) << " by " << generator;
|
||||
|
||||
auto *data = yyjson_mut_obj_get(root, "data");
|
||||
if (!data || !yyjson_mut_is_obj(data))
|
||||
auto *data = yyjson_obj_get(root, "data");
|
||||
if (!data || !yyjson_is_obj(data))
|
||||
{
|
||||
Log(this) << "Unable to read " << dbname << ": data element is missing or not an object";
|
||||
return { nullptr, nullptr };
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return { doc, data };
|
||||
DBData ret;
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_val *key, *val;
|
||||
yyjson_obj_foreach(data, idx, max, key, val)
|
||||
{
|
||||
if (!yyjson_is_str(key))
|
||||
{
|
||||
Log(this) << "Unable to read part of " << dbname << ": key of data element #" << idx << " is not a string";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto keystr = yyjson_get_astr(key);
|
||||
if (!yyjson_is_arr(val))
|
||||
{
|
||||
Log(this) << "Unable to read part of " << dbname << ": " << keystr << " value of data element #" << idx << " is not an array";
|
||||
continue;
|
||||
}
|
||||
|
||||
Log(LOG_DEBUG) << "Loading " << yyjson_arr_size(val) << " " << keystr << " records";
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_val *elem;
|
||||
yyjson_arr_foreach(val, idx, max, elem)
|
||||
{
|
||||
Data ld(elem);
|
||||
ret.emplace(keystr, std::move(ld));
|
||||
}
|
||||
}
|
||||
|
||||
yyjson_doc_free(doc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void UpdateMetadata(yyjson_mut_doc *doc, yyjson_mut_val *obj)
|
||||
void SaveType(yyjson_mut_doc *doc, yyjson_mut_val *obj, const Anope::string &typestr, const Data &data)
|
||||
{
|
||||
const auto generator = "Anope " + Anope::Version();
|
||||
yyjson_mut_obj_upsert(doc, obj, "generator", yyjson_mut_strncpy(doc, generator.c_str(), generator.length()));
|
||||
yyjson_mut_obj_upsert(doc, obj, "version", yyjson_mut_uint(doc, ANOPE_DATABASE_VERSION));
|
||||
yyjson_mut_obj_upsert(doc, obj, "updated", yyjson_mut_int(doc, Anope::CurTime));
|
||||
auto *type = yyjson_mut_obj_getn(obj, typestr.c_str(), typestr.length());
|
||||
if (!type || !yyjson_mut_is_arr(type))
|
||||
{
|
||||
// We haven't seen this element before.
|
||||
type = yyjson_mut_arr(doc);
|
||||
yyjson_mut_obj_add_val(doc, obj, typestr.c_str(), type);
|
||||
}
|
||||
|
||||
auto *elem = yyjson_mut_obj(doc);
|
||||
if (data.id)
|
||||
yyjson_mut_obj_add_uint(doc, elem, "@id", data.id);
|
||||
|
||||
for (const auto &[key, value] : data.data)
|
||||
{
|
||||
yyjson_mut_val *v;
|
||||
switch (data.GetType(key))
|
||||
{
|
||||
case Serialize::DataType::BOOL:
|
||||
v = yyjson_mut_bool(doc, Anope::Convert<bool>(value.str(), false));
|
||||
break;
|
||||
case Serialize::DataType::FLOAT:
|
||||
v = yyjson_mut_real(doc, Anope::Convert<double>(value.str(), 0.0));
|
||||
break;
|
||||
case Serialize::DataType::INT:
|
||||
v = yyjson_mut_int(doc, Anope::Convert<int64_t>(value.str(), 0));
|
||||
break;
|
||||
case Serialize::DataType::TEXT:
|
||||
{
|
||||
auto str = value.str();
|
||||
v = str.empty() ? yyjson_mut_null(doc) : yyjson_mut_strncpy(doc, str.c_str(), str.length());
|
||||
break;
|
||||
}
|
||||
case Serialize::DataType::UINT:
|
||||
v = yyjson_mut_uint(doc, Anope::Convert<uint64_t>(value.str(), 0));
|
||||
break;
|
||||
}
|
||||
|
||||
auto *k = yyjson_mut_strncpy(doc, key.c_str(), key.length());
|
||||
yyjson_mut_obj_add(elem, k, v);
|
||||
}
|
||||
|
||||
yyjson_mut_arr_add_val(type, elem);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -262,136 +346,90 @@ public:
|
||||
{
|
||||
auto dbname = GetDatabaseFile(nullptr);
|
||||
|
||||
auto [doc, data] = ReadDatabase(dbname);
|
||||
if (!data)
|
||||
auto db = ReadDatabase(dbname);
|
||||
if (!db)
|
||||
return EVENT_STOP;
|
||||
|
||||
for (const auto &type : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
auto *s_type = Serialize::Type::Find(type);
|
||||
if (!s_type || !s_type->GetOwner())
|
||||
continue;
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_mut_val *elem;
|
||||
yyjson_mut_arr_foreach(data, idx, max, elem)
|
||||
{
|
||||
Data ld(elem);
|
||||
s_type->Unserialize(nullptr, ld);
|
||||
}
|
||||
if (s_type && !s_type->GetOwner())
|
||||
LoadType(s_type, db.value());
|
||||
}
|
||||
|
||||
loaded = false;
|
||||
loaded = true;
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
void OnSaveDatabase() override
|
||||
{
|
||||
std::set<Module *> updated;
|
||||
for (const auto &[_, s_type] : Serialize::Type::GetTypes())
|
||||
// Step 1: clear the old data.
|
||||
for (const auto &type : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
auto *s_type = Serialize::Type::Find(type);
|
||||
if (!s_type)
|
||||
continue; // Provider has been unloaded.
|
||||
|
||||
auto it = databases.find(s_type->GetOwner());
|
||||
if (it == databases.end())
|
||||
{
|
||||
auto *doc = yyjson_mut_doc_new(nullptr);
|
||||
|
||||
auto *root = yyjson_mut_obj(doc);
|
||||
yyjson_mut_doc_set_root(doc, root);
|
||||
|
||||
UpdateMetadata(doc, root);
|
||||
|
||||
auto *data = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_val(doc, root, "data", data);
|
||||
|
||||
databases[s_type->GetOwner()] = { doc, data };
|
||||
databases.emplace(s_type->GetOwner(), DBData());
|
||||
continue; // We just need to create for this type.
|
||||
}
|
||||
else if (updated.find(s_type->GetOwner()) == updated.end())
|
||||
{
|
||||
auto *doc = it->second.first;
|
||||
auto *root = yyjson_mut_doc_get_root(doc);
|
||||
|
||||
UpdateMetadata(doc, root);
|
||||
updated.insert(s_type->GetOwner());
|
||||
}
|
||||
// As this type has been written before we need to clear the entries
|
||||
// from the previous writes so we can update it in the next loop. We
|
||||
// have to do it this way so we don't purge any entries for unloaded
|
||||
// modules.
|
||||
it->second.erase(s_type->GetName());
|
||||
}
|
||||
|
||||
std::set<Serialize::Type *> seen;
|
||||
// Step 2: store the new data.
|
||||
for (auto *item : Serializable::GetItems())
|
||||
{
|
||||
auto *s_type = item->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue; // Provider has been unloaded.
|
||||
|
||||
// This should always be found because we create it in the previous step.
|
||||
auto it = databases.find(s_type->GetOwner());
|
||||
if (it == databases.end())
|
||||
continue; // Type has not been registered?
|
||||
|
||||
auto &[doc, data] = it->second;
|
||||
|
||||
// If the type object doesn't exist then create it. Otherwise, clear.
|
||||
// all of the previous objects stored in it.
|
||||
auto *type = yyjson_mut_obj_getn(data, s_type->GetName().c_str(), s_type->GetName().length());
|
||||
if (!type || yyjson_mut_get_type(type) != YYJSON_TYPE_ARR)
|
||||
{
|
||||
// We haven't seen this element before.
|
||||
type = yyjson_mut_arr(doc);
|
||||
yyjson_mut_obj_add_val(doc, data, s_type->GetName().c_str(), type);
|
||||
}
|
||||
else if (seen.find(s_type) == seen.end())
|
||||
{
|
||||
// We are reusing an existing element, clear it.
|
||||
yyjson_mut_arr_clear(type);
|
||||
seen.insert(s_type);
|
||||
}
|
||||
|
||||
auto *elem = yyjson_mut_arr_add_obj(doc, type);
|
||||
if (item->id)
|
||||
yyjson_mut_obj_add_uint(doc, elem, "id", item->id);
|
||||
|
||||
Data sd;
|
||||
s_type->Serialize(item, sd);
|
||||
for (const auto &[key, value] : sd.data)
|
||||
{
|
||||
yyjson_mut_val *v;
|
||||
switch (sd.GetType(key))
|
||||
{
|
||||
case Serialize::DataType::BOOL:
|
||||
v = yyjson_mut_bool(doc, Anope::Convert<bool>(value.str(), false));
|
||||
break;
|
||||
case Serialize::DataType::FLOAT:
|
||||
v = yyjson_mut_real(doc, Anope::Convert<double>(value.str(), 0.0));
|
||||
break;
|
||||
case Serialize::DataType::INT:
|
||||
v = yyjson_mut_int(doc, Anope::Convert<int64_t>(value.str(), 0));
|
||||
break;
|
||||
case Serialize::DataType::TEXT:
|
||||
{
|
||||
auto str = value.str();
|
||||
v = str.empty() ? yyjson_mut_null(doc) : yyjson_mut_strncpy(doc, str.c_str(), str.length());
|
||||
break;
|
||||
}
|
||||
case Serialize::DataType::UINT:
|
||||
v = yyjson_mut_uint(doc, Anope::Convert<uint64_t>(value.str(), 0));
|
||||
break;
|
||||
}
|
||||
|
||||
auto *k = yyjson_mut_strncpy(doc, key.c_str(), key.length());
|
||||
yyjson_mut_obj_add(elem, k, v);
|
||||
}
|
||||
if (it != databases.end())
|
||||
it->second.emplace(s_type->GetName(), Data(s_type, item));
|
||||
}
|
||||
|
||||
// Step 3: serialize to JSON.
|
||||
for (auto &[mod, database] : databases)
|
||||
{
|
||||
auto dbname = GetDatabaseFile(mod);
|
||||
BackupDatabase(dbname);
|
||||
|
||||
auto *doc = yyjson_mut_doc_new(nullptr);
|
||||
|
||||
auto *root = yyjson_mut_obj(doc);
|
||||
yyjson_mut_doc_set_root(doc, root);
|
||||
|
||||
const auto generator = "Anope " + Anope::Version() + " " + Anope::VersionBuildString();
|
||||
yyjson_mut_obj_add_strncpy(doc, root, "generator", generator.c_str(), generator.length());
|
||||
yyjson_mut_obj_add_uint(doc, root, "version", ANOPE_DATABASE_VERSION);
|
||||
yyjson_mut_obj_add_int(doc, root, "updated", Anope::CurTime);
|
||||
|
||||
auto *data = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_val(doc, root, "data", data);
|
||||
|
||||
for (const auto &[name, items] : database)
|
||||
SaveType(doc, data, name, items);
|
||||
|
||||
Log(LOG_DEBUG) << "Writing " << dbname;
|
||||
|
||||
yyjson_write_err errmsg;
|
||||
const auto flags = YYJSON_WRITE_ALLOW_INVALID_UNICODE | YYJSON_WRITE_NEWLINE_AT_END | YYJSON_WRITE_PRETTY;
|
||||
if (!yyjson_mut_write_file(dbname.c_str(), database.first, flags, nullptr, &errmsg))
|
||||
if (!yyjson_mut_write_file(dbname.c_str(), doc, flags, nullptr, &errmsg))
|
||||
{
|
||||
Log(this) << "Unable to write " << dbname << ": error #" << errmsg.code << ": " << errmsg.msg;
|
||||
// TODO: exit??? retry???
|
||||
}
|
||||
|
||||
yyjson_mut_doc_free(doc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,21 +445,13 @@ public:
|
||||
const auto dbname = GetDatabaseFile(s_type->GetOwner());
|
||||
|
||||
auto db = ReadDatabase(dbname);
|
||||
if (!db.second)
|
||||
if (!db)
|
||||
return; // Not much we can do here.
|
||||
|
||||
it = databases.emplace(s_type->GetOwner(), db).first;
|
||||
it = databases.emplace(s_type->GetOwner(), std::move(db.value())).first;
|
||||
}
|
||||
|
||||
auto &[doc, data] = it->second;
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_mut_val *elem;
|
||||
yyjson_mut_arr_foreach(data, idx, max, elem)
|
||||
{
|
||||
Data ld(elem);
|
||||
s_type->Unserialize(nullptr, ld);
|
||||
}
|
||||
LoadType(s_type, it->second);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -174,9 +174,9 @@ public:
|
||||
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
|
||||
return;
|
||||
|
||||
Anope::string sql = Anope::printf("SELECT * from `%s`", GetTableName(obj).c_str());
|
||||
Anope::string sql = Anope::Format("SELECT * from `%s`", GetTableName(obj).c_str());
|
||||
if (obj->GetTimestamp())
|
||||
sql += Anope::printf(" WHERE (`timestamp` >= %s OR `timestamp` IS NULL)", this->SQL->FromUnixtime(obj->GetTimestamp()).c_str());
|
||||
sql += Anope::Format(" WHERE (`timestamp` >= %s OR `timestamp` IS NULL)", this->SQL->FromUnixtime(obj->GetTimestamp()).c_str());
|
||||
|
||||
Query query(sql);
|
||||
|
||||
|
||||
+41
-3
@@ -142,7 +142,7 @@ class Packet final
|
||||
record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3];
|
||||
pos += 4;
|
||||
|
||||
//record.rdlength = input[pos] << 8 | input[pos + 1];
|
||||
auto rdlength = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
switch (record.type)
|
||||
@@ -192,6 +192,44 @@ class Packet final
|
||||
|
||||
break;
|
||||
}
|
||||
case DNS::QUERY_TXT:
|
||||
{
|
||||
if (pos + rdlength > input_size)
|
||||
throw SocketException("Unable to unpack TXT resource record");
|
||||
|
||||
auto txtlength = input[pos++];
|
||||
if (pos + txtlength > input_size)
|
||||
throw SocketException("Unable to unpack TXT resource record");
|
||||
|
||||
record.rdata = Anope::string(reinterpret_cast<const char* >(input + pos), txtlength);
|
||||
pos += rdlength - 1;
|
||||
break;
|
||||
}
|
||||
case DNS::QUERY_SRV:
|
||||
{
|
||||
if (rdlength < 6 || pos + rdlength > input_size)
|
||||
throw SocketException("Unable to unpack SRV resource record");
|
||||
|
||||
auto srv = std::make_shared<DNS::Record::SRV>();
|
||||
|
||||
srv->priority = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
srv->weight = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
srv->port = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
srv->host = this->UnpackName(input, input_size, pos);
|
||||
if (!IsValidName(srv->host))
|
||||
throw SocketException("Invalid name in SRV resource record");
|
||||
|
||||
record.rdata = Anope::Format("%hu %hu %hu %s", srv->priority,
|
||||
srv->weight, srv->port, srv->host.c_str());
|
||||
record.rdataobj = srv;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -638,7 +676,7 @@ public:
|
||||
if (!packet)
|
||||
return false;
|
||||
|
||||
Log(LOG_DEBUG_2) << "Resolver: Notifying slave " << packet->addr.addr();
|
||||
Log(LOG_DEBUG_2) << "Resolver: Notifying secondary " << packet->addr.addr();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -939,7 +977,7 @@ public:
|
||||
|
||||
void Notify(const Anope::string &zone) override
|
||||
{
|
||||
/* notify slaves of the update */
|
||||
/* notify secondaries of the update */
|
||||
for (const auto &[ip, port] : notify)
|
||||
{
|
||||
sockaddrs addr;
|
||||
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
|
||||
public:
|
||||
EMD5(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
, md5provider(this, "md5", 16, 64)
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
|
||||
@@ -14,7 +14,7 @@ class ENone final
|
||||
{
|
||||
public:
|
||||
ENone(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
throw ModuleException("enc_none is deprecated and can not be used as a primary encryption method");
|
||||
@@ -35,9 +35,7 @@ public:
|
||||
if (!hash_method.equals_cs("plain"))
|
||||
return;
|
||||
|
||||
Anope::string b64pass;
|
||||
Anope::B64Encode(req->GetPassword(), b64pass);
|
||||
auto enc = "plain:" + b64pass;
|
||||
auto enc = "plain:" + Anope::B64Encode(req->GetPassword());
|
||||
if (nc->pass.equals_cs(enc))
|
||||
{
|
||||
// If we are NOT the first encryption module we want to re-encrypt
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/* Include file for high-level encryption routines.
|
||||
*
|
||||
* (C) 2003-2025 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"
|
||||
#include "modules/encryption.h"
|
||||
|
||||
class EOld final
|
||||
: public Module
|
||||
{
|
||||
private:
|
||||
ServiceReference<Encryption::Provider> md5;
|
||||
|
||||
Anope::string EncryptInternal(const Anope::string &src)
|
||||
{
|
||||
if (!md5)
|
||||
return {};
|
||||
|
||||
char digest[32];
|
||||
memset(digest, 0, sizeof(digest));
|
||||
|
||||
auto hash = md5->Encrypt(src);
|
||||
if (hash.length() != sizeof(digest))
|
||||
return {}; // Probably a bug?
|
||||
memcpy(digest, hash.data(), hash.length());
|
||||
|
||||
char digest2[16];
|
||||
for (size_t i = 0; i < sizeof(digest); i += 2)
|
||||
digest2[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]);
|
||||
|
||||
return Anope::Hex(digest2, sizeof(digest2));
|
||||
}
|
||||
|
||||
inline static char XTOI(char c)
|
||||
{
|
||||
return c > 9 ? c - 'A' + 10 : c - '0';
|
||||
}
|
||||
|
||||
public:
|
||||
EOld(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
, md5("Encryption::Provider", "md5")
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
throw ModuleException("enc_old is deprecated and can not be used as a primary encryption method");
|
||||
|
||||
ModuleManager::LoadModule("enc_md5", User::Find(creator, true));
|
||||
if (!md5)
|
||||
throw ModuleException("Unable to find md5 reference");
|
||||
}
|
||||
|
||||
void OnCheckAuthentication(User *, IdentifyRequest *req) override
|
||||
{
|
||||
const auto *na = NickAlias::Find(req->GetAccount());
|
||||
if (!na)
|
||||
return;
|
||||
|
||||
NickCore *nc = na->nc;
|
||||
size_t pos = nc->pass.find(':');
|
||||
if (pos == Anope::string::npos)
|
||||
return;
|
||||
|
||||
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
|
||||
if (!hash_method.equals_cs("oldmd5"))
|
||||
return;
|
||||
|
||||
auto enc = EncryptInternal(req->GetPassword());
|
||||
if (!enc.empty() && nc->pass.equals_cs(enc))
|
||||
{
|
||||
// If we are NOT the first encryption module we want to re-encrypt
|
||||
// the password with the primary encryption method.
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
|
||||
Anope::Encrypt(req->GetPassword(), nc->pass);
|
||||
req->Success(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(EOld)
|
||||
@@ -173,7 +173,7 @@ private:
|
||||
|
||||
public:
|
||||
ESHA1(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
, sha1provider(this, "sha1", 20, 64)
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
|
||||
@@ -17,14 +17,6 @@ class ESHA256 final
|
||||
{
|
||||
private:
|
||||
unsigned iv[8];
|
||||
bool use_iv;
|
||||
|
||||
/* initializes the IV with a new random value */
|
||||
void NewRandomIV()
|
||||
{
|
||||
for (auto &ivsegment : iv)
|
||||
ivsegment = static_cast<uint32_t>(Anope::RandomNumber());
|
||||
}
|
||||
|
||||
/* returns the IV as base64-encrypted string */
|
||||
Anope::string GetIVString()
|
||||
@@ -50,11 +42,6 @@ private:
|
||||
|
||||
Anope::string EncryptInternal(const Anope::string &src)
|
||||
{
|
||||
if (!use_iv)
|
||||
NewRandomIV();
|
||||
else
|
||||
use_iv = false;
|
||||
|
||||
sha256_ctx ctx;
|
||||
sha256_init(&ctx);
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
@@ -69,9 +56,8 @@ private:
|
||||
|
||||
public:
|
||||
ESHA256(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
{
|
||||
use_iv = false;
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
throw ModuleException("enc_sha256 is deprecated and can not be used as a primary encryption method");
|
||||
}
|
||||
@@ -92,7 +78,6 @@ public:
|
||||
return;
|
||||
|
||||
GetIVFromPass(nc->pass);
|
||||
use_iv = true;
|
||||
auto enc = EncryptInternal(req->GetPassword());
|
||||
if (nc->pass.equals_cs(enc))
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user